Subversion Repositories DevTools

Rev

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