Subversion Repositories DevTools

Rev

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};
5359 dpurdie 545
        $entry->{release}{LXRSTATE} = 'D' unless (exists $entry->{release}{LXRSTATE});
5252 dpurdie 546
        Information("Entry: $entry->{release}{Project}, $entry->{release}{Name}, $entry->{release}{LXRSTATE}, $rtagid");
547
        next if ($entry->{release}{LXRSTATE} eq 'D');
5359 dpurdie 548
 
5209 dpurdie 549
        $entry->{release}{VersionsString} = join( ',', map { '"' . $_ .'"'} @{$entry->{Versions}} );
550
        $entry->{release}{dbName} = genDatabaseName($rtagid);
5213 dpurdie 551
        $entry->{release}{root} = catdir($ReleaseStore, $rtagid );
5209 dpurdie 552
        #DebugDumpData("ENTRY", \$entry);
5359 dpurdie 553
        my $stateTxt = $entry->{release}{ACTIVE} ? 'Active' : 'InActive';
554
        #$stateTxt .= ' [' . $entry->{release}{ACTIVE} . ']';
5209 dpurdie 555
 
5359 dpurdie 556
 
5209 dpurdie 557
        my $tfileName = 'lxr.tree.template';
558
        open( my $tf, '<', $tfileName) || Error ("Cannot open $tfileName. $!");
559
        while (my $line = <$tf>)
560
        {
561
            # Chomp trailing write space
562
            $line =~ s~\s+$~~;
563
 
564
            #   Replace known bits in the template
565
            $line =~ s~\@CAPTION\@~$entry->{release}{Project}::$entry->{release}{Name}~g;
566
            $line =~ s~\@SHORT_NAME\@~$rtagid~g;
567
            $line =~ s~\@RELEASE_ROOT\@~$entry->{release}{root}~g;
568
            $line =~ s~\@VERSIONS_LIST\@~$entry->{release}{VersionsString}~g;
569
            $line =~ s~\@DBNAME\@~$entry->{release}{dbName}~g;
5359 dpurdie 570
            $line =~ s~\@STATE\@~$stateTxt~g;
5209 dpurdie 571
            push @lxrTreeText, $line
572
        }
573
        close $tf;
574
    }
575
 
576
    #
577
    #   Insert tree sections into the main config file template
578
    #
579
    my $hostList = join( ',', map { '\'http://' . $_ .'\''} @addressList );
580
 
581
    my $tfileName = catfile($scriptDir, 'lxr.template');
5213 dpurdie 582
    my $lxrFileName = catfile($Config->{lxr}, 'lxr.new.conf');
5209 dpurdie 583
    unlink $lxrFileName;
584
    open( my $tf, '<', $tfileName) || Error ("Cannot open $tfileName. $!");
585
    open( my $to, '>', $lxrFileName) || Error ("Cannot open $lxrFileName. $!");
586
    while (my $line = <$tf>)
587
    {
588
        # Chomp trailing write space
589
        $line =~ s~\s+$~~;
590
 
591
        #   Replace known bits in the template
592
        if ($line =~ m~\@TREE_SECTIONS\@~)
593
        {
594
            foreach (@lxrTreeText)
595
            {
596
                print $to $_, "\n";
597
            }
598
        }
599
        else
600
        {
601
            $line =~ s~\@HOSTLIST\@~$hostList~g;
602
            print $to $line, "\n";
603
        }
604
    }
605
    close $tf;
606
    close $to;
607
 
608
    #
609
    #   Install the new config files
610
    #
5213 dpurdie 611
    my $lxrLive = catfile($Config->{lxr}, 'lxr.conf');
612
    my $lxrBackup = catfile($Config->{lxr}, 'lxr.conf.bak');
5209 dpurdie 613
    unlink $lxrBackup;
614
    rename ($lxrLive, $lxrBackup) || Warning("Renaming $lxrLive, $lxrBackup", $!);
615
    rename ($lxrFileName, $lxrLive) || Warning("Renaming $lxrFileName, $lxrLive", $!);
616
 
617
    #
618
    #   Create new database tables if required
619
    #   Use a customized shell script to do the hard work
620
    #
5213 dpurdie 621
    foreach my $rtagid ( sort keys %ReleaseData )
5209 dpurdie 622
    {
623
        my $entry = $ReleaseData{$rtagid};
5359 dpurdie 624
        next if ($entry->{release}{LXRSTATE} eq 'D');
5213 dpurdie 625
        Verbose("Database:$entry->{release}{Name}, $entry->{release}{dbName} ");
5209 dpurdie 626
        System('--NoExit', '--NoShell', catfile($scriptDir, 'lxr.initdb.sh'), $entry->{release}{dbName});
627
    }
628
}
629
 
630
#-------------------------------------------------------------------------------
631
# Function        : buildIndexes 
632
#
633
# Description     : Build (Generate) indexes for all versions of all releases
634
#                   that don't have an index
635
#                   
636
#                   Place a marker file in the 'version' directory when the
637
#                   index has been created
638
#
639
#                   Notes:
5359 dpurdie 640
#                   The 'genxref' program needs to be run from the lxr install directory
5209 dpurdie 641
#                   chdir to that directory for each invocation
642
#
643
#                   genxref uses DBI - and must find the proper PERL DBI and not the one
644
#                   within JATS.. Solution:
645
#                       Kill the PERL5LIB EnvVar
646
#
647
#
648
#
649
# Inputs          : 
650
#
651
# Returns         : 
652
#
653
sub buildIndexes
654
{
655
    #
656
    #   Prep envonment for calling genxref
657
    #   See notes above
658
    #
5213 dpurdie 659
    chdir ($Config->{lxr}) || Error ("Cannot chnage directory:$Config->{lxr}, $!");
5209 dpurdie 660
    delete $ENV{PERL5LIB};
661
 
662
    #
663
    #   Examine each Version in each Release
664
    #   Generate command line like:
665
    #   genxref --tree RTAGID --url http://HOSTNAME/lxr --version 'VERSION'
5213 dpurdie 666
    foreach my $rtagid ( sort keys %ReleaseData )
5209 dpurdie 667
    {
668
        my $entry = $ReleaseData{$rtagid};
669
        foreach my $version (@{$entry->{Versions}})
670
        {
5213 dpurdie 671
            my $markerFile = catfile(catdir($ReleaseStore, $rtagid ), $version, '.lxrIndexed');
5209 dpurdie 672
            unless (-f $markerFile) {
673
                Message("Must index: $rtagid, $version");
674
                my $rv = System('--NoExit', 
675
                       '--NoShell', 
5213 dpurdie 676
                       catfile($Config->{lxr}, 'genxref'),
5209 dpurdie 677
                       '--url', 'http://' . $ENV{GBE_HOSTNAME} . '/lxr',
678
                       '--tree', $rtagid,
679
                       '--version', $version
680
                       );
681
               Verbose("genxref exit: $rv");
682
               unless ($rv) {
683
                   TouchFile($markerFile);
684
               }
5252 dpurdie 685
               else
686
               {
687
                   Warning("Error indexing $rtagid ($rv)");
688
               }
5209 dpurdie 689
            }
690
            else
691
            {
692
                Verbose("Already indexed: $rtagid, $version");
693
            }
694
        }
695
    }
696
    #
697
    #   Restore current directory
698
    #
699
    chdir($FileUtils::CwdFull);
700
}
701
 
702
 
703
#-------------------------------------------------------------------------------
704
# Function        : cleanReleaseViews 
705
#
706
# Description     : Clean up unused Releases and Release Views
707
#                   Maintain the list of retained versions
708
#
709
#                   Two classes
710
#                   Active - Marked as having LXR support
711
#                       Retain the last 5 Versions
712
#
713
#                  InActive - Not having LXR support
714
#                       Retain for 10 days then delete all versions
715
#
716
# Inputs          : 
717
#
718
# Returns         : 
719
#
720
sub cleanReleaseViews
721
{
722
    #
723
    #   Scan Releases and delete all that are not currently configured
724
    #
725
    opendir (my $rdir, $ReleaseStore) || Error ("Cannot open directory: $ReleaseStore", $!);
726
    while (my $rdirEntry = readdir($rdir))
727
    {
728
        #   Skip hidden files and directories
729
        next if ($rdirEntry =~ m~^\.~);
730
        my $vdirName = catdir($ReleaseStore, $rdirEntry );
731
        next unless ( -d $vdirName );
5212 dpurdie 732
        unless(exists $ReleaseData{$rdirEntry} && $ReleaseData{$rdirEntry}{release}{ACTIVE} )
5209 dpurdie 733
        {
5211 dpurdie 734
            #   Release is no longer configured - age it out
5209 dpurdie 735
            #   Assume $rdirEntry is an rtag_id
5247 dpurdie 736
            $ReleaseData{$rdirEntry}{release}{LXRSTATE} = 'C';
5213 dpurdie 737
            if (processAgeMarker($vdirName, $Config->{'releaseAge'} ))
5211 dpurdie 738
            {
5247 dpurdie 739
                $ReleaseData{$rdirEntry}{release}{LXRSTATE} = 'D';
5211 dpurdie 740
                Message("Delete Release: $rdirEntry");
741
                RmDirTree($vdirName);
742
                System('--NoExit', '--NoShell', catfile($scriptDir, 'lxr.dropdb.sh'), genDatabaseName($rdirEntry));
5231 dpurdie 743
                if ( defined $Config->{glimpseDir} )
744
                {
745
                    my $glimpseData = catdir( $Config->{glimpseDir}, $rdirEntry );
5855 dpurdie 746
                    Message("Delete Glimpse Subdir: $glimpseData");
5231 dpurdie 747
                    RmDirTree($glimpseData);
748
                }
5211 dpurdie 749
            }
5252 dpurdie 750
            else
751
            {
752
                #
753
                #   Build up the list of known versions
754
                #
755
                foreach my $entry ( getReleaseVersions($vdirName) )
756
                {
757
                    push @{$ReleaseData{$rdirEntry}{Versions}}, $entry->{name};
758
                }
759
            }
5209 dpurdie 760
        }
761
        else
762
        {
5247 dpurdie 763
            $ReleaseData{$rdirEntry}{release}{LXRSTATE} = 'I';
5211 dpurdie 764
            deleteAgeMarker($vdirName);
5209 dpurdie 765
 
766
            #   Release is configured
767
            #   Keep the last x created
768
            #   Note: Create time is a kludge
769
            #
770
            #   Process each version within the Release
771
            #
772
            my $keepCount = 0;
5252 dpurdie 773
            foreach my $entry ( getReleaseVersions($vdirName) )
5209 dpurdie 774
            {
5359 dpurdie 775
                #DebugDumpData("$rdirEntry, getReleaseVersions:Entry", $entry);
5209 dpurdie 776
                $keepCount++;
777
                if ($keepCount > 5)
778
                {
779
                    #   Version is no longer needed - remove it
5359 dpurdie 780
                    #   Remove glimpse data too
5209 dpurdie 781
                    Message("Delete Version: $rdirEntry, $entry->{name}, $entry->{ctime}");
782
                    RmDirTree($entry->{path});
5359 dpurdie 783
                    if ( defined $Config->{glimpseDir} )
784
                    {
785
                        my $glimpseEntry = catdir( $Config->{glimpseDir}, $rdirEntry, $entry->{name} );
5855 dpurdie 786
                        Message("Delete Glimpse Data: $glimpseEntry");
5359 dpurdie 787
                        RmDirTree($glimpseEntry);
5855 dpurdie 788
                        Warning("Glimpse Data Dir still present: $glimpseEntry") if ( -d $glimpseEntry);
5359 dpurdie 789
                    }
5209 dpurdie 790
                }
791
                else
792
                {
793
                    #   Note which versions we have
794
                    push @{$ReleaseData{$rdirEntry}{Versions}}, $entry->{name};
795
                }
796
            }
797
        }
798
    }
799
    close ($rdir);
800
}
801
 
802
#-------------------------------------------------------------------------------
5252 dpurdie 803
# Function        : getReleaseVersions 
804
#
805
# Description     : Get the Versions in a Release
806
#
807
# Inputs          : $vdirName         - Path to process
808
#
809
# Returns         : A sorted array of data items (Most recent first)
810
#                   Each items consists of:
811
#                       {name}
812
#                       {path}
813
#                       {ctime}    
814
#
815
sub getReleaseVersions
816
{
817
    my ($vdirName) = @_;
818
    my @versionData;
819
 
820
    opendir (my $vdir, $vdirName) || Warning ("Cannot open directory: $vdirName", $!);
821
    while (my $vdirEntry = readdir($vdir))
822
    {
823
        #   Skip hidden files and directories
824
        next if ($vdirEntry =~ m~^\.~);
825
        my $ldirName = catdir($vdirName, $vdirEntry );
826
        next unless ( -d $ldirName );
827
        my $data;
828
        $data->{name} = $vdirEntry; 
829
        $data->{path} = $ldirName; 
830
        $data->{ctime} = (stat $ldirName)[9];
831
        push @versionData  , $data;
832
    }
833
    close ($vdir);
834
    #DebugDumpData("versionData",\@versionData);
835
 
836
    my @sortedList = sort { $b->{ctime} <=> $a->{ctime}} @versionData;
837
    #DebugDumpData("SortedVersionData",\@sortedList);
838
    return @sortedList;
839
}
840
 
841
 
842
#-------------------------------------------------------------------------------
5209 dpurdie 843
# Function        : getLatestVersion 
844
#
845
# Description     : For a specified directory return the newest subdir
846
#
847
#                   Used to determine the most recent version
848
#
5212 dpurdie 849
# Inputs          : $vdirName - Dir to process - expecting a Release directory
5209 dpurdie 850
#
5213 dpurdie 851
# Returns         : latestName  - Patch to the latest directory
852
#                   Age (days ) - Of the named directory
5209 dpurdie 853
#
854
sub getLatestVersion
855
{
856
    my  ($vdirName) = @_;
857
    my $latestName;
858
    my $latestAge = 0;
859
 
5213 dpurdie 860
    if (-d $vdirName )
5209 dpurdie 861
    {
5213 dpurdie 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~^\.~);
5209 dpurdie 867
 
5213 dpurdie 868
            my $ldirName = catdir($vdirName, $vdirEntry );
869
            next unless ( -d $ldirName );
5209 dpurdie 870
 
5213 dpurdie 871
            my $age = (stat $ldirName)[9];
872
            Verbose3("Age: $ldirName, $age");
5209 dpurdie 873
 
5213 dpurdie 874
            if  ($age > $latestAge )
875
            {
876
                $latestAge = $age;
877
                $latestName = $ldirName;
878
            }
5209 dpurdie 879
        }
5213 dpurdie 880
        close ($vdir);
881
 
882
        #   Convert to Days ago
883
        $latestAge = ($StampTime - $latestAge) / (60*60*24);
884
        #DebugDumpData("versionDataSorted",\@versionDataSorted);
885
        Verbose("Latest: $latestName, $latestAge");
5209 dpurdie 886
    }
5213 dpurdie 887
    else
888
    {
889
        Verbose("Latest: No directory found: $vdirName");
890
    }
5209 dpurdie 891
 
5213 dpurdie 892
    return $latestName, $latestAge;
5209 dpurdie 893
}
894
 
895
#-------------------------------------------------------------------------------
896
# Function        : cleanPackageStore 
897
#
5231 dpurdie 898
# Description     : Delete unused Packages from the package store
899
#                   Each View in each Release will have a .lxrRelease file that contains the
900
#                   package versions that the view needs.
5209 dpurdie 901
#
902
# Inputs          : 
903
#
904
# Returns         : 
905
#
906
sub cleanPackageStore
907
{
5231 dpurdie 908
    Verbose ("cleanPackageStore");
5209 dpurdie 909
    my %pkgsUsed;
910
    #
911
    #   Examime ALL versions in ALL Releases and build up a hash of
912
    #   Package Versions used
913
    #
914
    opendir (my $rdir, $ReleaseStore) || Error ("Cannot open directory: $ReleaseStore", $!);
915
    while (my $rdirEntry = readdir($rdir))
916
    {
917
        #   Skip hidden files and directories
918
        next if ($rdirEntry =~ m~^\.~);
919
        my $vdirName = catdir($ReleaseStore, $rdirEntry );
920
        next unless ( -d $vdirName );
921
 
922
        #
923
        #   Process each version within the Release
924
        #
925
        opendir (my $vdir, $vdirName) || Warning ("Cannot open directory: $vdirName", $!);
926
        while (my $vdirEntry = readdir($vdir))
927
        {
928
            #   Skip hidden files and directories
929
            next if ($vdirEntry =~ m~^\.~);
930
            my $ldirName = catdir($vdirName, $vdirEntry );
931
            next unless ( -d $ldirName );
932
 
933
            #
5231 dpurdie 934
            #   Read in the View List
5209 dpurdie 935
            #
5231 dpurdie 936
            my $releaseListFile = catfile($ldirName, '.lxrRelease');
937
            if (open (my $rf, '<', $releaseListFile ))
5209 dpurdie 938
            {
5231 dpurdie 939
                Verbose2("Found ", $releaseListFile);
940
                while (my $data = <$rf>)
5209 dpurdie 941
                {
5231 dpurdie 942
                    $data =~ s~\s+$~~;
943
                    $pkgsUsed{$data}++;
5209 dpurdie 944
                }
945
            }
5231 dpurdie 946
            else
947
            {
948
                Warning ("Cannot find Release List: $releaseListFile", $!);
949
            }
5209 dpurdie 950
        }
951
        close ($vdir);
952
    }
953
    close ($rdir);
954
 
955
    #
956
    #   Process the Packages directory and remove those not currently used
957
    #
958
    #
959
    #   Process each entry within the Version
960
    #
961
    opendir (my $pdir, $PackageStore) || Error ("Cannot open directory: $PackageStore", $!);
962
    while (my $pdirEntry = readdir($pdir))
963
    {
964
        #   Skip hidden files and directories
965
        next if ($pdirEntry =~ m~^\.~);
966
        my $pdirName = catdir($PackageStore, $pdirEntry );
967
        next unless ( -d $pdirName );
968
        next if (exists $pkgsUsed{$pdirEntry} );
969
 
5213 dpurdie 970
        if (processAgeMarker($pdirName, $Config->{packageAge})) 
5211 dpurdie 971
        {
972
            Message("Purge Package: $pdirEntry");
973
            RmDirTree($pdirName);
974
        }
5209 dpurdie 975
    }
976
    close ($pdir);
977
 
978
    #DebugDumpData("pkgsUsed", \%pkgsUsed);
979
}
980
 
981
#-------------------------------------------------------------------------------
982
# Function        : getReleaseData 
983
#
984
# Description     : Get all the required Release Data 
985
#
986
# Inputs          :  
987
#
988
# Returns         : 
989
#
990
sub getReleaseData
991
{
992
    my ($rtagid) = @_;
993
    my (@row);
5212 dpurdie 994
    my @releaseList;
995
    my $partSql = '';
5209 dpurdie 996
 
5213 dpurdie 997
    Verbose("getReleaseData");
5209 dpurdie 998
    connectRM(\$RM_DB) unless $RM_DB;
999
 
5212 dpurdie 1000
    #
1001
    #   Determine list of existing Releases
1002
    #   Build up a Clause for the extraction SQL
1003
    #   This is used to get data for Releases that exist in the Store but may have been
1004
    #   deconfigured.
1005
    #
1006
    if ( opendir (my $rdir, $ReleaseStore) )
1007
    {
1008
        while (my $rdirEntry = readdir($rdir))
1009
        {
1010
            #   Skip hidden files and directories
1011
            next if ($rdirEntry =~ m~^\.~);
1012
            my $vdirName = catdir($ReleaseStore, $rdirEntry );
1013
            next unless ( -d $vdirName );
1014
            push @releaseList, $rdirEntry;
1015
        }
1016
        close $rdir;
1017
    }
5209 dpurdie 1018
 
5212 dpurdie 1019
    if (@releaseList)
1020
    {
1021
        $partSql = ' OR rt.rtag_id in (' . join(',', @releaseList ) . ')' 
1022
    }
1023
 
1024
 
5209 dpurdie 1025
    #
1026
    # Determine which Releases need LXR support
1027
    #
1028
    my $m_sqlstr = 
5247 dpurdie 1029
        "SELECT rt.rtag_id," .
1030
        "  rt.proj_id," .
1031
        "  p.PROJ_NAME," .
1032
        "  rt.rtag_name," .
1033
        "  rt.official," .
1034
        "  NVL(TRUNC (SYSDATE - rt.official_stamp),0) AS OFFICIAL_STAMP_DAYS," .
1035
        "  rt.lxr,".
1036
        "  lxr.lxrserver" .
1037
        " FROM release_manager.release_tags rt," .
1038
        "  release_manager.lxr_state lxr," .
1039
        "  release_manager.projects p" .
1040
        " WHERE lxr.RTAG_ID(+) = rt.RTAG_ID" .
1041
        " AND (rt.lxr = 'Y'" . $partSql . ")" .
1042
        " AND p.PROJ_ID = rt.proj_id";
5209 dpurdie 1043
 
5247 dpurdie 1044
    Verbose2('$m_sqlstr',$m_sqlstr);
5209 dpurdie 1045
    my $sth = $RM_DB->prepare($m_sqlstr);
1046
    if ( defined($sth) )
1047
    {
1048
        if ( $sth->execute( ) )
1049
        {
1050
            if ( $sth->rows )
1051
            {
1052
                while ( @row = $sth->fetchrow_array )
1053
                {
1054
                    my $rtagid = $row[0];
1055
                    my $data;
1056
                    $data->{Project} = $row[2];
1057
                    $data->{Name} = $row[3];
1058
                    $data->{official} = substr($row[4],0,1);
1059
                    $data->{official_stamp_days} = $row[5];
5212 dpurdie 1060
                    $data->{lxr} = $row[6];
5247 dpurdie 1061
                    $data->{lxr_state} = $row[7] || 'N';
5209 dpurdie 1062
 
1063
                    #
1064
                    #   Determine if this request for an LXR release is OK
1065
                    #   Ok If the release is Open, CCB or Restricted
5212 dpurdie 1066
                    #   Ok If closed and has been closed to < 10 days
5209 dpurdie 1067
                    #
5212 dpurdie 1068
                    if ($data->{lxr} eq 'Y')
5209 dpurdie 1069
                    {
5212 dpurdie 1070
                        if (index('NRC', $data->{official}) >= 0)
1071
                        {
1072
                            $data->{ACTIVE} = 1;
1073
                        }
1074
                        elsif ($data->{official} eq 'Y' && $data->{official_stamp_days} < 10 )
1075
                        {
1076
                            $data->{ACTIVE} = 2;
1077
                        }
5209 dpurdie 1078
                    }
1079
 
1080
                    $ReleaseData{$rtagid}{release} = $data;
1081
                }
1082
            }
1083
            $sth->finish();
1084
        }
1085
    }
1086
    else
1087
    {
1088
        Error("getReleaseData:Prepare failure" );
1089
    }
1090
 
5213 dpurdie 1091
    if (IsVerbose(1))
1092
    {
1093
        DebugDumpData("ReleaseData", \%ReleaseData);
1094
    }
5212 dpurdie 1095
 
5213 dpurdie 1096
    #
1097
    #   Just a summary display for logging
1098
    #
1099
    foreach my $rtagid ( sort keys %ReleaseData)
5209 dpurdie 1100
    {
5213 dpurdie 1101
        my $state = $ReleaseData{$rtagid}{release}{ACTIVE} ? 'ACTIVE' : 'InActive';
1102
        Information("Release: RtagId $rtagid, $state");
5209 dpurdie 1103
    }
1104
}
1105
 
1106
#-------------------------------------------------------------------------------
5213 dpurdie 1107
# Function        : getReleasePakageData
5209 dpurdie 1108
#
5212 dpurdie 1109
# Description     : Get PackgeVersion information for one Release
5209 dpurdie 1110
#
1111
# Inputs          : rtagid
1112
#
1113
# Returns         : 
1114
#
5213 dpurdie 1115
sub getReleasePakageData
5209 dpurdie 1116
{
1117
    my ($rtagid) = @_;
1118
    my (@row);
1119
 
1120
    connectRM(\$RM_DB) unless $RM_DB;
1121
 
1122
 
1123
    # Get details for each package in the Release
1124
    #   Don't worry about dependent packages
1125
    #
1126
    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)".
1127
                   " FROM RELEASE_MANAGER.RELEASE_CONTENT rc, RELEASE_MANAGER.PACKAGE_VERSIONS pv, RELEASE_MANAGER.PACKAGES pkg" .
1128
                   " WHERE rc.RTAG_ID = $rtagid AND rc.PV_ID = pv.PV_ID AND pv.PKG_ID = pkg.PKG_ID";
1129
    my $sth = $RM_DB->prepare($m_sqlstr);
1130
    if ( defined($sth) )
1131
    {
1132
        if ( $sth->execute( ) )
1133
        {
1134
            if ( $sth->rows )
1135
            {
1136
                while ( @row = $sth->fetchrow_array )
1137
                {
1138
                    my $data;
1139
                    my $pvid = $row[0];
1140
                    unless (exists $Packages{$pvid}) {
1141
                        $data->{pv_id} = $row[0];
1142
                        $data->{name} = $row[1];
1143
                        $data->{ver} = $row[2];
1144
                        $data->{ext} = $row[3] || '';
1145
                        $data->{vcs} = $row[4] || '';
1146
                        $Packages{$pvid} = $data;
1147
                    }
5212 dpurdie 1148
                    $ReleaseData{$rtagid}{data}{$pvid} = 1;
5209 dpurdie 1149
                }
1150
            }
1151
            $sth->finish();
1152
        }
1153
    }
1154
    else
1155
    {
5213 dpurdie 1156
        Error("getReleasePakageData:Prepare failure" );
5209 dpurdie 1157
    }
1158
}
1159
 
1160
#-------------------------------------------------------------------------------
5247 dpurdie 1161
# Function        : updateReleaseManager 
1162
#
1163
# Description     : Feed the state of the releases back into the Release
1164
#                   manager database
1165
#                   
1166
#                   Assumes that the user has write access to ONE table
1167
#
1168
# Inputs          : 
1169
#
1170
# Returns         : 
1171
#
1172
sub updateReleaseManager
1173
{
1174
    foreach my $rtagid ( keys %ReleaseData)
1175
    {
1176
        my $rentry = $ReleaseData{$rtagid}{release}; 
1177
        Verbose3("updateReleaseManager:", $rtagid, $rentry->{lxr_state}, $rentry->{LXRSTATE});
1178
 
1179
        #
1180
        #   Only update those that have changed
1181
        #
1182
        if ($rentry->{lxr_state} ne $rentry->{LXRSTATE})
1183
        {
1184
            my $m_sqlstr;
1185
            #
1186
            #   Have just deleted the entry
1187
            #
1188
            if ($rentry->{LXRSTATE} eq 'D')
1189
            {
5359 dpurdie 1190
                unless ($rentry->{lxr_state} eq 'N') {
1191
                    simpleSqlExecute('updateReleaseManager',"DELETE from release_manager.lxr_state where rtag_id = " . $rtagid);
1192
                }
5247 dpurdie 1193
            }
1194
            elsif ($rentry->{LXRSTATE} eq 'C')
1195
            {
1196
                my $state = 'C';
1197
                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; ");
1198
            }
1199
            elsif ($rentry->{LXRSTATE} eq 'I')
1200
            {
1201
                my $state = 'I';
1202
                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; ");
1203
            }
1204
            else
1205
            {
1206
                Warning("updateReleaseManager. No entry for $rtagid");
1207
            }
1208
        }
1209
    }
1210
}
1211
 
1212
#-------------------------------------------------------------------------------
1213
# Function        : simpleSqlExecute 
1214
#
1215
# Description     : Perform a simple SQL statement that does not return anything
1216
#                   Used to update the RM database 
1217
#
1218
# Inputs          : $pname          - proceedure name ( for logging)
1219
#                   $m_sqlstr       - Sql to process
1220
#                    
1221
#
1222
# Returns         : 
1223
#
1224
sub simpleSqlExecute
1225
{
1226
    my ($pname,$m_sqlstr) = @_;
1227
    my (@row);
1228
 
1229
    connectRM(\$RM_DB) unless $RM_DB;
1230
 
1231
    Verbose2($pname,$m_sqlstr);
1232
    my $sth = $RM_DB->prepare($m_sqlstr);
1233
    if ( defined($sth) )
1234
    {
1235
        if ( $sth->execute( ) )
1236
        {
1237
            $sth->finish();
1238
        }
1239
        else
1240
        {
1241
            Warning("$pname.Execute failure: $m_sqlstr", $sth->errstr() );
1242
        }
1243
    }
1244
    else
1245
    {
1246
        Error("$pname:Prepare failure" );
1247
    }
1248
}
1249
 
1250
#-------------------------------------------------------------------------------
5209 dpurdie 1251
# Function        : genDatabaseName 
1252
#
1253
# Description     : Genertate the name of a database
1254
#
1255
# Inputs          : rtag_id 
1256
#
1257
# Returns         : Text Name of the database
1258
#
1259
 
1260
sub genDatabaseName
1261
{
1262
    my ($rtag_id) = @_;
1263
    return 'LXR_' . $rtag_id;
1264
}
1265
 
1266
#-------------------------------------------------------------------------------
1267
# Function        : readConfig 
1268
#
1269
# Description     : Read the basic LXR config
1270
#                   This is held in a Perl structure 
1271
#
1272
# Inputs          : None 
1273
#
1274
# Returns         : Populate Global Data
1275
#
1276
sub readConfig
1277
{
1278
    my $cfile = catfile($scriptDir,'jats_lxr.conf');
5211 dpurdie 1279
    if ($opt_config)
1280
    {
1281
        Message ("Using alternate config: $opt_config");
1282
        $cfile = $opt_config;
1283
    }
5209 dpurdie 1284
 
5213 dpurdie 1285
    #
1286
    #   Slurp in the file and evaluate it as a perl expression
1287
    #
1288
    if (open(my $CONFIG, '<', $cfile))
1289
    {
1290
        local ($/) = undef;
1291
        my $config_contents = <$CONFIG>;
1292
        $config_contents =~ m/(.*)/s;
1293
        $config_contents = $1;    #untaint it
1294
        my $config = eval("\n#line 1 \"configuration file\"\n" . $config_contents);
1295
        Error($@) if $@;
1296
        close $CONFIG;
5209 dpurdie 1297
 
5213 dpurdie 1298
        #
1299
        #   Merge read data with defaults
1300
        #
1301
        @$Config{ keys %$config } = values %$config;
1302
    }
1303
    else
1304
    {
1305
        Error("Couldn't open configuration file \"$cfile\".", $!);
1306
    }
5209 dpurdie 1307
}
1308
 
1309
#-------------------------------------------------------------------------------
1310
# Function        : startLogFile 
1311
#
1312
# Description     : Start logging to a log file
1313
#                   Generate a nice name for the log file
1314
#
1315
# Inputs          : 
1316
#
1317
# Returns         : 
1318
#
1319
sub startLogFile
1320
{
1321
    if ( $opt_logfile )
1322
    {
5213 dpurdie 1323
        if (exists $Config->{lxrLogDir})
5209 dpurdie 1324
        {
5213 dpurdie 1325
            my ($sec,$min,$hour,$mday,$mon,$year,$wday,$yday,$isdst) = gmtime($StampTime);
5209 dpurdie 1326
            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 1327
            $name = catdir($Config->{lxrLogDir}, $name);
5209 dpurdie 1328
 
5213 dpurdie 1329
            mkpath($Config->{lxrLogDir}); 
1330
            if (-d $Config->{lxrLogDir} )
5209 dpurdie 1331
            {
1332
                open STDOUT, '>', $name  or die "Can't redirect STDOUT: $!";
1333
                open STDERR, ">&STDOUT"  or die "Can't dup STDOUT: $!";
5252 dpurdie 1334
                STDOUT->autoflush(1);
1335
                STDERR->autoflush(1);
5209 dpurdie 1336
            }
1337
            else
1338
            {
5213 dpurdie 1339
                Warning("Can't create log dir: $Config->{lxrLogDir}. $!");
5209 dpurdie 1340
            }
1341
        }
1342
    }
1343
}
1344
 
1345
#-------------------------------------------------------------------------------
1346
# Function        : cleanupLogFiles 
1347
#
1348
# Description     : Remove old log files
1349
#
1350
# Inputs          : 
1351
#
1352
# Returns         : 
1353
#
1354
sub cleanupLogFiles
1355
{
5213 dpurdie 1356
    if (exists $Config->{lxrLogDir} && exists $Config->{logAge}  && $Config->{logAge} > 0 )
5209 dpurdie 1357
    {
5213 dpurdie 1358
        Verbose("cleanupLogFiles:$Config->{lxrLogDir}, $Config->{logAge}");
1359
        if ( opendir my $logDir, $Config->{lxrLogDir} )
5209 dpurdie 1360
        {
1361
            foreach my $fileName (readdir $logDir)
1362
            {
5213 dpurdie 1363
                my $file = catfile($Config->{lxrLogDir}, $fileName);
5209 dpurdie 1364
                next unless -f $file;
5213 dpurdie 1365
                next unless -M $file > $Config->{logAge};
5209 dpurdie 1366
                Verbose("Purge logfile: $fileName");
1367
                unlink $file;
1368
            }
1369
            closedir $logDir;
1370
        }
1371
    }
1372
}
1373
 
5211 dpurdie 1374
#-------------------------------------------------------------------------------
1375
# Function        : processAgeMarker 
1376
#
1377
# Description     : Age out directories
1378
#                   Will create age markers as required
1379
#
1380
# Inputs          : $tdir       - Target Directory
1381
#                   $age        - Configured age 
1382
#
1383
# Returns         : true        - Directory has reached age
1384
#
1385
sub processAgeMarker
1386
{
1387
    my ($tdir, $age) = @_;
1388
 
1389
    unless (-d $tdir) {
1390
        Warning ("Expected directory not found: $tdir");
5359 dpurdie 1391
        return 1; 
5211 dpurdie 1392
    }
5209 dpurdie 1393
 
5211 dpurdie 1394
    #   A configured age of 0 implies delete immediatly
1395
    if ($age == 0)
1396
    {
1397
        return 1;
1398
    }
1399
 
5252 dpurdie 1400
    #   Test for Age me now marker file
1401
    my $purgefile = catfile($tdir, '.lxrPurge');
1402
    if (-f $purgefile )
1403
    {
1404
        Verbose ("Age:  ForcedPurge $tdir");
1405
        return 1;
1406
    }
1407
 
5211 dpurdie 1408
    #
1409
    #   Create the file ONCE
1410
    #
1411
    my $markerfile = catfile($tdir, '.lxrAge');
1412
    unless (-f $markerfile)
1413
    {
1414
        TouchFile($markerfile);
1415
    }
1416
    else
1417
    {
5213 dpurdie 1418
        my $fileAge = -M $markerfile;
1419
        Verbose ("Age: $fileAge, $tdir");
1420
        if ($fileAge > $age)
5211 dpurdie 1421
        {
1422
            return 1
1423
        }
1424
    }
1425
    return 0;
1426
}
1427
 
1428
 
5209 dpurdie 1429
#-------------------------------------------------------------------------------
5211 dpurdie 1430
# Function        : deleteAgeMarker 
1431
#
1432
# Description     : Delete any age marker
1433
#                   Used when a (potentially) agable directory is used to remove
1434
#                   the aging marker
1435
#
1436
# Inputs          :  $tdir      - Directory
1437
#
1438
# Returns         : 
1439
#
1440
sub deleteAgeMarker
1441
{
1442
    my ($tdir) = @_;
1443
 
1444
    unless (-d $tdir) {
1445
        Warning ("Expected directory not found: $tdir");
1446
        return 0; 
1447
    }
1448
 
1449
    #
1450
    #   Use same file name as in processAgeMarker
1451
    #
1452
    my $markerfile = catfile($tdir, '.lxrAge');
1453
    unlink $markerfile;
1454
}
1455
 
5233 dpurdie 1456
#-------------------------------------------------------------------------------
1457
# Function        : baseVersionNumber 
1458
#
1459
# Description     : Remove the build number from a package-version string 
1460
#
1461
# Inputs          : Package-Version string 
1462
#
1463
# Returns         : Version String with a build # of 0
1464
#                   Will return a non-standard string, but one that can be used for comparisons
1465
#
1466
sub baseVersionNumber
1467
{
1468
    my ($version) = @_;
1469
    my $iversion = $version;
5211 dpurdie 1470
 
5233 dpurdie 1471
    #
1472
    #   Look for a patchRipple.suffix
1473
    #
1474
    if ( $version =~ m~(.*?)\.([0-9]{4,6})(\.\w+)$~ )
1475
    {
1476
        my $part1 = $1;
1477
        my $patch = $2;
1478
        my $suffix = $3;
1479
        my $build;
1480
 
1481
        if ( length( $patch) >= 4 )
1482
        {
1483
            $build = substr( $patch, -3 ,3);
1484
            $patch = substr( $patch,  0 ,length($patch)-3);
1485
 
1486
            $version = $part1 . sprintf (".%3.3d.%3.3d", $patch, 0) . $suffix;
1487
        }
1488
    }
1489
    else
1490
    {
1491
        Verbose("baseVersionNumber. Could not massge: $iversion");
1492
    }
1493
    return $version;
1494
}
1495
 
1496
 
5211 dpurdie 1497
#-------------------------------------------------------------------------------
5209 dpurdie 1498
#   Documentation
1499
#
1500
 
1501
=pod
1502
 
1503
=head1 NAME
1504
 
1505
jats_lxr - Maintain LXR Releases
1506
 
1507
=head1 SYNOPSIS
1508
 
1509
  jats jats_lxr [options]
1510
 
1511
 Options:
1512
    -help               - brief help message
1513
    -help -help         - Detailed help message
1514
    -man                - Full documentation
1515
    -[no]createVersions - Create new versions. Default:Create
1516
    -[no]extract        - Extract source code. Default:Extract
1517
    -[no]index          - Index new LXR versions. Default:Index
1518
    -[no]purge          - Purge unused packages. Default:Purge
1519
    -[no]logfile        - Capture out to a log file. Default:Log
5231 dpurdie 1520
    -[no]forceViews     - Force creation of new views. Default:NoForceView
5211 dpurdie 1521
    -config=file        - Alternate config file
5209 dpurdie 1522
 
1523
=head1 OPTIONS
1524
 
1525
=over 8
1526
 
1527
=item B<-help>
1528
 
1529
Print a brief help message and exits.
1530
 
1531
=item B<-help -help>
1532
 
1533
Print a detailed help message with an explanation for each option.
1534
 
1535
=item B<-man>
1536
 
1537
Prints the manual page and exits.
1538
 
1539
=item B<-verbose>
1540
 
1541
This option will display progress information as the program executes.
1542
 
1543
=item B<-[no]createVersions>
1544
 
1545
This option can be used to suppress the creation of new views.
1546
 
1547
=item B<-[no]extract>
1548
 
1549
This option can be used to suppress the extraction of source.
1550
 
1551
=item B<-[no]index>
1552
 
1553
This option can be used to suppress the indexing of newly created views.
1554
 
1555
=item B<-[no]purge>
1556
 
1557
This option can be used to suppress purging of packages that are no longer used by any of the LXR Trees.
1558
 
5231 dpurdie 1559
=item B<-[no]forceViews>
1560
 
1561
This option can be used to force the creation of a new View in each Release.
1562
 
5211 dpurdie 1563
=item B<-config=file>
1564
 
1565
This option can be used to override the standard config file. Used in testing.
1566
 
5209 dpurdie 1567
=back
1568
 
1569
=head1 DESCRIPTION
1570
 
1571
This program is a tool for creating and maintaining an LXR instance within the VIX Build System.
1572
 
1573
The program can:
1574
 
1575
=over 8
1576
 
1577
=item * 
1578
 
1579
Examine the Release Manager Database and determine which Releases are a part of the set to have LXR Views created.
1580
 
1581
Releases that are Open (or Restricted or in CCB Mode) or that have been closed for less than 10 days will be processed.
1582
 
1583
=item *
1584
 
1585
Examine the Release Manager Database and determine the package-versions that are a part of the LXR Release Set.
1586
 
1587
The process will only examine the contents of a Release. It will not descend the version dependency tree.
1588
 
1589
The program will then extract new package-versions into it's Package Store. Multiple LXR Tree's will share the one 
1590
instance of the extracted source code.
1591
 
1592
=item *
1593
 
1594
Create a new 'Version' for each Release.
1595
 
1596
The Version Name is based on the date-time at which the process is run.
1597
 
1598
Each Version is a symlink to the required package-version held in the Package Store.
1599
 
1600
This step can be suppressed though a command line option.
1601
 
1602
=item *
1603
 
1604
Remove unused LXR Trees (Releases no longer being processed) and unused Versions within each Tree.
1605
 
1606
Releases that are no longer eligable for processing will be retained for 10 days and then deleted. 
1607
During this time the existing versions will not be aged out.
1608
 
1609
At the moment this tool simply retains the last 5 Versions of each Release. If the tool 
1610
is run nightly then this will translate into  5 days.
1611
 
1612
=item *
1613
 
1614
Regenerate the LXR Configuration file
1615
 
1616
Create new database tables for new Releases
1617
 
1618
=item *
1619
 
1620
Run the LXR indexer for each LXR Version that has not been processed. Once processed the Version will 
1621
be tagged to prevent further indexing.
1622
 
1623
=item *
1624
 
1625
Remove unused Package-Versions from the Package Store.
1626
 
1627
=back
1628
 
1629
=cut
1630