Subversion Repositories DevTools

Rev

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