Subversion Repositories DevTools

Rev

Rev 5211 | Go to most recent revision | Details | 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
#
9
# Description   : Tiools to maintain LXR information
10
#
11
# Usage         : See POD at the end of this file
12
#
13
#......................................................................#
14
 
15
require 5.008_002;
16
use strict;
17
use warnings;
18
 
19
use Pod::Usage;
20
use Getopt::Long;
21
use File::Path;
22
use FindBin;
23
use Socket;
24
 
25
use JatsError;
26
use JatsRmApi;
27
use DBI;
28
use JatsSystem;
29
use FileUtils;
30
 
31
#
32
#   Config Options
33
#
34
my $VERSION = "1.0.0";                      # Update this
35
my $opt_help = 0;
36
my $opt_verbose = $ENV{'GBE_VERBOSE'};      # Allow global verbose
37
my $opt_createVersions = 1;
38
my $opt_index = 1;
39
my $opt_purge = 1;
40
my $opt_extract = 1;
41
my $opt_logfile = 1;
42
 
43
 
44
#
45
#   Globals
46
#
47
my $scriptDir;
48
my $RM_DB;
49
our $config;
50
my @addressList;
51
my %ReleaseData;
52
my %Packages;
53
my $PackageStore;
54
my $ReleaseStore;
55
my $stamptime = time;
56
 
57
#-------------------------------------------------------------------------------
58
# Function        : Main
59
#
60
# Description     : Main entry point
61
#                   Parse user options
62
#
63
# Inputs          :
64
#
65
# Returns         :
66
#
67
 
68
my $result = GetOptions (
69
                "help:+"            => \$opt_help,              # flag, multiple use allowed
70
                "manual:3"          => \$opt_help,              # flag, multiple use allowed
71
                "verbose:+"         => \$opt_verbose,           # flag
72
                "createVersions!"   => \$opt_createVersions,
73
                "purge!"            => \$opt_purge,
74
                "index!"            => \$opt_index,
75
                "extract!"          => \$opt_extract,
76
                "logfile!"         => \$opt_logfile,
77
                );
78
 
79
#
80
#   Process help and manual options
81
#
82
pod2usage(-verbose => 0, -message => "Version: $VERSION")  if ($opt_help == 1  || ! $result);
83
pod2usage(-verbose => 1)  if ($opt_help == 2 );
84
pod2usage(-verbose => 2)  if ($opt_help > 2);
85
 
86
#
87
#   Capture all logging to a file
88
#   Could be done by the jats wrapper, but this way we can control its location
89
#
90
ErrorConfig( 'name'    => 'LXR',
91
             'verbose' => $opt_verbose );
92
 
93
#
94
#   Sanity test
95
#
96
 
97
$scriptDir = $FindBin::Bin;
98
InitFileUtils();
99
 
100
#
101
#   Read the tool configuration
102
#
103
readConfig();
104
Error ("No LXR Data directory defined", $config->{lxrFiles}) unless( exists $config->{lxrFiles});
105
Error ("No LXR Data directory found", $config->{lxrFiles}) unless( -d $config->{lxrFiles});
106
Error ("No LXR Install directory defined",$config->{lxr}) unless( exists $config->{lxr});
107
Error ("No LXR Install directory found",$config->{lxr}) unless( -d $config->{lxr});
108
 
109
#
110
#   Start logging
111
#
112
startLogFile();
113
Message ("Start of LXR. " . localtime(time) ) if $opt_logfile;
114
Message("ScriptDir: $scriptDir");
115
 
116
#
117
#   Check required paths exist
118
#
119
$PackageStore = catdir($config->{lxrFiles}, 'Packages');
120
$ReleaseStore = catdir($config->{lxrFiles}, 'Releases');
121
mkpath($PackageStore);
122
mkpath($ReleaseStore);
123
Error ("Package Store not found ",$PackageStore) unless( -d $PackageStore);
124
Error ("Release Store not found ",$ReleaseStore) unless( -d $ReleaseStore);
125
 
126
#
127
#   Determine the various names for this machine
128
#   Include all the IP addresses too
129
#
130
my ($canonname, $aliases, $addrtype, $length, @addrs) = gethostbyname($ENV{GBE_HOSTNAME});
131
push @addressList, $canonname ;
132
push (@addressList, $aliases) if ($aliases) ;
133
push (@addressList, $ENV{GBE_HOSTNAME});
134
foreach ( @addrs) {
135
    push @addressList, inet_ntoa($_); 
136
}
137
Message("IpAddress: @addressList");
138
 
139
#
140
#   Perform the hard work
141
#
142
getReleaseData();
143
determineDataToExtract();
144
createReleaseViews() if $opt_createVersions;
145
cleanReleaseViews();
146
rebuildLxrConfig();
147
buildIndexes() if $opt_index;
148
cleanPackageStore() if $opt_purge;
149
cleanupLogFiles() if $opt_purge;
150
 
151
#
152
#   All done
153
#
154
Message ("End of LXR. " . localtime(time) ) if $opt_logfile;
155
exit 0;
156
 
157
#-------------------------------------------------------------------------------
158
# Function        : determineDataToExtract 
159
#
160
# Description     : Determine the packages that need to be extracted
161
#                   Don't extract them if they already exist
162
#
163
# Inputs          : 
164
#
165
# Returns         : 
166
#
167
sub determineDataToExtract
168
{
169
    foreach my $pvid ( keys{%Packages})
170
    {
171
        my $entry = $Packages{$pvid};
172
        #DebugDumpData("Entry", \$entry);
173
        my $fullName = join('_', $entry->{name}, $entry->{ver});
174
        my $fullPath = catfile($PackageStore , $fullName);
175
        next unless defined $entry->{vcs};
176
        next if ( $entry->{vcs} ) =~ m~^UC::~;
177
        unless (-d $fullPath ) {
178
            Message("Need to extract: $entry->{name}, $entry->{ver}");
179
            if ($opt_extract)
180
            {
181
                Verbose0("Extracting into: $fullPath");
182
                my $rv = JatsCmd ('jats_vcsrelease', '-devmode=escrow', '-extractfiles', "-view=$fullName", "-label=$entry->{vcs}", "-root=$PackageStore", "-noprefix");
183
                print "$fullName : SUCCESS\n" unless $rv;
184
                print "$fullName : ERROR\n" if $rv;
185
                $entry->{bad} = 1;
186
            }
187
        }
188
    }
189
}
190
 
191
#-------------------------------------------------------------------------------
192
# Function        : createReleaseViews 
193
#
194
# Description     : Create a new view for each Release
195
#                   Each view is basically a bunch of symlinks
196
#
197
# Inputs          : 
198
#
199
# Returns         : 
200
#
201
sub createReleaseViews
202
{
203
    #
204
    #   Create a name for the releases - based on a date-time
205
    #   Will be unqiue(ish)
206
    #
207
    my $dateTag = localtime($stamptime);
208
 
209
    foreach my $rtagid (keys \%ReleaseData)
210
    {
211
        my $entry = $ReleaseData{$rtagid};
212
        my $latestView = getLatestVersion(catdir($ReleaseStore, $rtagid));
213
        my  $needNewView = 1;
214
 
215
        #
216
        #   Check to see if we really need to create a new view
217
        #   If the LATEST view contins all the package-versions that we need then
218
        #   don't create a new one.
219
        #
220
        #   Scan each entry within the Last View
221
        #
222
        if ($latestView)
223
        {
224
            my %pkgsUsed;
225
            opendir (my $ldir, $latestView) || Warning ("Cannot open directory: $latestView", $!);
226
            while (my $ldirEntry = readdir($ldir))
227
            {
228
                #   Skip hidden files
229
                next if ($ldirEntry =~ m~^\.~);
230
                my $dirName = catdir($latestView, $ldirEntry );
231
 
232
                #
233
                #   Process each entry within the Version
234
                #
235
                my $pkgName = $ldirEntry;
236
                if (-l $dirName)
237
                {
238
                    $pkgName = readlink($dirName);
239
                    $pkgName =~ s~.*/~~;
240
                }
241
                $pkgsUsed{$pkgName} = 2;
242
            }
243
            close ($ldir);
244
 
245
            #
246
            #   Compare Package-Versions against those we need
247
            # 
248
            foreach my $pvid (keys $entry->{data})
249
            {
250
                my $entry = $Packages{$pvid};
251
                my $fullName = join('_', $entry->{name}, $entry->{ver});
252
                $pkgsUsed{$fullName}++;
253
            }
254
 
255
            #
256
            #   Scan the pkgUsed
257
            #   A value of 1 indicates that it is used only in the New Version
258
            #   A value of 2 indicates that it is only used on the Last Version
259
            #   A value of 3 indicates that its used in both
260
            #   Detect those that are not a 3
261
            #
262
            $needNewView = 0;
263
            foreach ( keys %pkgsUsed)
264
            {
265
                if ($pkgsUsed{$_} != 3)
266
                {
267
                    $needNewView = 1;
268
                    last;
269
                }
270
            }
271
            #DebugDumpData("pkgsUsed",\%pkgsUsed);
272
        }
273
 
274
        unless ($needNewView)
275
        {
276
            Message("No Changes to LXR View: $rtagid");
277
        }
278
        else
279
        {
280
            Message("Creating LXR View: $rtagid, $dateTag");
281
            my $releaseDir = catdir($ReleaseStore, $rtagid, $dateTag);
282
            mkpath($releaseDir);
283
            if (-d $releaseDir)
284
            {
285
                #
286
                #   Insert metadata
287
                #   Used to allow ordering and aging of the releases
288
                #    
289
                my $metaDataName = catfile( $releaseDir, '.jatslxr');
290
                open (my $md, '>' , $metaDataName) || Error ("Cannot create $metaDataName, $!");
291
                print $md $stamptime;
292
                close $md;
293
 
294
                #
295
                #   Populate with symlinks to the actual package-versions
296
                #
297
                foreach my $pvid (keys $entry->{data})
298
                {
299
                    my $entry = $Packages{$pvid};
300
                    my $alias = join('', $entry->{name}, $entry->{ext});
301
                    my $fullName = join('_', $entry->{name}, $entry->{ver});
302
                    my $PackageStore = catdir($PackageStore , $fullName);
303
                    my $releaseDir = catdir($releaseDir, $alias );
304
                    next if -l $releaseDir;
305
 
306
                    Verbose("Symlink $PackageStore, $releaseDir");
307
                    my $rv = symlink ($PackageStore, $releaseDir);
308
                    unless ($rv)
309
                    {
310
                        Warning("Could not link $PackageStore, $releaseDir")
311
                    }
312
                }
313
            }
314
        }
315
    }
316
}
317
 
318
#-------------------------------------------------------------------------------
319
# Function        : rebuildLxrConfig 
320
#
321
# Description     : Rebuild the LXR Configuration file
322
#                   This MAY be a bit LXR version specific, but since LXR doesn't
323
#                   provide a scriptable way to update configuration
324
#
325
#                   Uses template files that have been handcrafted after taken from
326
#                   LXR. Basically we to a text repplace a glue together
327
#
328
#                   For each release we need
329
#                       Long Release Name
330
#                       Short Release Name
331
#                       List of Versions
332
#
333
#
334
# Inputs          : Assumes Data has been added to %ReleaseData by other subroutines
335
#
336
# Returns         : 
337
#
338
sub rebuildLxrConfig
339
{
340
    my @lxrTreeText;
341
    #
342
    #   Process configured releases
343
    #
344
    #DebugDumpData("ReleaseData", \%ReleaseData);
345
    foreach my $rtagid ( keys %ReleaseData )
346
    {
347
        my $entry = $ReleaseData{$rtagid};
348
        Information("Entry:$entry->{release}{Name}, $rtagid");
349
        $entry->{release}{VersionsString} = join( ',', map { '"' . $_ .'"'} @{$entry->{Versions}} );
350
        $entry->{release}{dbName} = genDatabaseName($rtagid);
351
        #DebugDumpData("ENTRY", \$entry);
352
 
353
        my $tfileName = 'lxr.tree.template';
354
        open( my $tf, '<', $tfileName) || Error ("Cannot open $tfileName. $!");
355
        while (my $line = <$tf>)
356
        {
357
            # Chomp trailing write space
358
            $line =~ s~\s+$~~;
359
 
360
            #   Replace known bits in the template
361
            $line =~ s~\@CAPTION\@~$entry->{release}{Project}::$entry->{release}{Name}~g;
362
            $line =~ s~\@SHORT_NAME\@~$rtagid~g;
363
            $line =~ s~\@RELEASE_ROOT\@~$entry->{release}{root}~g;
364
            $line =~ s~\@VERSIONS_LIST\@~$entry->{release}{VersionsString}~g;
365
            $line =~ s~\@DBNAME\@~$entry->{release}{dbName}~g;
366
            push @lxrTreeText, $line
367
        }
368
        close $tf;
369
    }
370
 
371
    #
372
    #   Insert tree sections into the main config file template
373
    #
374
    my $hostList = join( ',', map { '\'http://' . $_ .'\''} @addressList );
375
 
376
    my $tfileName = catfile($scriptDir, 'lxr.template');
377
    my $lxrFileName = catfile($config->{lxr}, 'lxr.new.conf');
378
    unlink $lxrFileName;
379
    open( my $tf, '<', $tfileName) || Error ("Cannot open $tfileName. $!");
380
    open( my $to, '>', $lxrFileName) || Error ("Cannot open $lxrFileName. $!");
381
    while (my $line = <$tf>)
382
    {
383
        # Chomp trailing write space
384
        $line =~ s~\s+$~~;
385
 
386
        #   Replace known bits in the template
387
        if ($line =~ m~\@TREE_SECTIONS\@~)
388
        {
389
            foreach (@lxrTreeText)
390
            {
391
                print $to $_, "\n";
392
            }
393
        }
394
        else
395
        {
396
            $line =~ s~\@HOSTLIST\@~$hostList~g;
397
            print $to $line, "\n";
398
        }
399
    }
400
    close $tf;
401
    close $to;
402
 
403
    #
404
    #   Install the new config files
405
    #
406
    my $lxrLive = catfile($config->{lxr}, 'lxr.conf');
407
    my $lxrBackup = catfile($config->{lxr}, 'lxr.conf.bak');
408
    unlink $lxrBackup;
409
    rename ($lxrLive, $lxrBackup) || Warning("Renaming $lxrLive, $lxrBackup", $!);
410
    rename ($lxrFileName, $lxrLive) || Warning("Renaming $lxrFileName, $lxrLive", $!);
411
 
412
    #
413
    #   Create new database tables if required
414
    #   Use a customized shell script to do the hard work
415
    #
416
    foreach my $rtagid ( keys %ReleaseData )
417
    {
418
        my $entry = $ReleaseData{$rtagid};
419
        Information("Database:$entry->{release}{Name}, $entry->{release}{dbName} ");
420
        System('--NoExit', '--NoShell', catfile($scriptDir, 'lxr.initdb.sh'), $entry->{release}{dbName});
421
    }
422
}
423
 
424
#-------------------------------------------------------------------------------
425
# Function        : buildIndexes 
426
#
427
# Description     : Build (Generate) indexes for all versions of all releases
428
#                   that don't have an index
429
#                   
430
#                   Place a marker file in the 'version' directory when the
431
#                   index has been created
432
#
433
#                   Notes:
434
#                   The 'genxref' program needs to be run from the lxr insatll directory
435
#                   chdir to that directory for each invocation
436
#
437
#                   genxref uses DBI - and must find the proper PERL DBI and not the one
438
#                   within JATS.. Solution:
439
#                       Kill the PERL5LIB EnvVar
440
#
441
#
442
#
443
# Inputs          : 
444
#
445
# Returns         : 
446
#
447
sub buildIndexes
448
{
449
    #
450
    #   Prep envonment for calling genxref
451
    #   See notes above
452
    #
453
    chdir ($config->{lxr}) || Error ("Cannot chnage directory:$config->{lxr}, $!");
454
    delete $ENV{PERL5LIB};
455
 
456
    #
457
    #   Examine each Version in each Release
458
    #   Generate command line like:
459
    #   genxref --tree RTAGID --url http://HOSTNAME/lxr --version 'VERSION'
460
    foreach my $rtagid ( keys %ReleaseData )
461
    {
462
        my $entry = $ReleaseData{$rtagid};
463
        foreach my $version (@{$entry->{Versions}})
464
        {
465
            my $markerFile = catfile($entry->{release}{root}, $version, '.lxrIndexed');
466
            unless (-f $markerFile) {
467
                Message("Must index: $rtagid, $version");
468
                my $rv = System('--NoExit', 
469
                       '--NoShell', 
470
                       catfile($config->{lxr}, 'genxref'),
471
                       '--url', 'http://' . $ENV{GBE_HOSTNAME} . '/lxr',
472
                       '--tree', $rtagid,
473
                       '--version', $version
474
                       );
475
               Verbose("genxref exit: $rv");
476
               unless ($rv) {
477
                   TouchFile($markerFile);
478
               }
479
            }
480
            else
481
            {
482
                Verbose("Already indexed: $rtagid, $version");
483
            }
484
        }
485
    }
486
    #
487
    #   Restore current directory
488
    #
489
    chdir($FileUtils::CwdFull);
490
}
491
 
492
 
493
#-------------------------------------------------------------------------------
494
# Function        : cleanReleaseViews 
495
#
496
# Description     : Clean up unused Releases and Release Views
497
#                   Maintain the list of retained versions
498
#
499
#                   Two classes
500
#                   Active - Marked as having LXR support
501
#                       Retain the last 5 Versions
502
#
503
#                  InActive - Not having LXR support
504
#                       Retain for 10 days then delete all versions
505
#
506
# Inputs          : 
507
#
508
# Returns         : 
509
#
510
sub cleanReleaseViews
511
{
512
    #
513
    #   Scan Releases and delete all that are not currently configured
514
    #
515
    opendir (my $rdir, $ReleaseStore) || Error ("Cannot open directory: $ReleaseStore", $!);
516
    while (my $rdirEntry = readdir($rdir))
517
    {
518
        #   Skip hidden files and directories
519
        next if ($rdirEntry =~ m~^\.~);
520
        my $vdirName = catdir($ReleaseStore, $rdirEntry );
521
        next unless ( -d $vdirName );
522
        unless(exists $ReleaseData{$rdirEntry} && $ReleaseData{$rdirEntry}{release}{LXR} )
523
        {
524
            #   Release is no longer configured - remove it
525
            #   Assume $rdirEntry is an rtag_id
526
            Message("Delete Release: $rdirEntry");
527
            RmDirTree($vdirName);
528
            my $entry = $ReleaseData{$rdirEntry};
529
            #DebugDumpData("ReleaseData:",$entry);
530
            System('--NoExit', '--NoShell', catfile($scriptDir, 'lxr.dropdb.sh'), genDatabaseName($rdirEntry));
531
        }
532
        else
533
        {
534
            $ReleaseData{$rdirEntry}{release}{root} = $vdirName;
535
 
536
            #   Release is configured
537
            #   Keep the last x created
538
            #   Note: Create time is a kludge
539
            #
540
            #   Process each version within the Release
541
            #
542
            my @versionData;
543
            opendir (my $vdir, $vdirName) || Warning ("Cannot open directory: $vdirName", $!);
544
            while (my $vdirEntry = readdir($vdir))
545
            {
546
                #   Skip hidden files and directories
547
                next if ($vdirEntry =~ m~^\.~);
548
                my $ldirName = catdir($vdirName, $vdirEntry );
549
                next unless ( -d $ldirName );
550
                my $data;
551
                $data->{name} = $vdirEntry; 
552
                $data->{path} = $ldirName; 
553
                $data->{ctime} = (stat $ldirName)[9];
554
                push @versionData  , $data;
555
            }
556
            close ($vdir);
557
            #DebugDumpData("versionData",\@versionData);
558
 
559
            my $keepCount = 0;
560
            foreach my $entry ( sort { $b->{ctime} <=> $a->{ctime}} @versionData )
561
            {
562
                #DebugDumpData("Entry", $entry);
563
                $keepCount++;
564
                if ($keepCount > 5)
565
                {
566
                    #   Version is no longer needed - remove it
567
                    Message("Delete Version: $rdirEntry, $entry->{name}, $entry->{ctime}");
568
                    RmDirTree($entry->{path});
569
                }
570
                else
571
                {
572
                    #   Note which versions we have
573
                    push @{$ReleaseData{$rdirEntry}{Versions}}, $entry->{name};
574
                }
575
            }
576
        }
577
    }
578
    close ($rdir);
579
}
580
 
581
#-------------------------------------------------------------------------------
582
# Function        : getLatestVersion 
583
#
584
# Description     : For a specified directory return the newest subdir
585
#
586
#                   Used to determine the most recent version
587
#
588
# Inputs          : Dir to process - expecting a Release directory
589
#
590
# Returns         : 
591
#
592
sub getLatestVersion
593
{
594
    my  ($vdirName) = @_;
595
    my $latestName;
596
    my $latestAge = 0;
597
 
598
    opendir (my $vdir, $vdirName) || Warning ("Cannot open directory: $vdirName", $!);
599
    while (my $vdirEntry = readdir($vdir))
600
    {
601
        #   Skip hidden files and directories
602
        next if ($vdirEntry =~ m~^\.~);
603
 
604
        my $ldirName = catdir($vdirName, $vdirEntry );
605
        next unless ( -d $ldirName );
606
 
607
        my $age = (stat $ldirName)[9];
608
        Verbose3("Age: $ldirName, $age");
609
 
610
        if  ($age > $latestAge )
611
        {
612
            $latestAge = $age;
613
            $latestName = $ldirName;
614
        }
615
    }
616
    close ($vdir);
617
 
618
    Verbose("Latest: $latestName, $latestAge");
619
    #DebugDumpData("versionDataSorted",\@versionDataSorted);
620
    return $latestName;
621
}
622
 
623
 
624
#-------------------------------------------------------------------------------
625
# Function        : cleanPackageStore 
626
#
627
# Description     : Delete unused PAckages fromthe package store
628
#
629
# Inputs          : 
630
#
631
# Returns         : 
632
#
633
sub cleanPackageStore
634
{
635
    my %pkgsUsed;
636
    #
637
    #   Examime ALL versions in ALL Releases and build up a hash of
638
    #   Package Versions used
639
    #
640
    opendir (my $rdir, $ReleaseStore) || Error ("Cannot open directory: $ReleaseStore", $!);
641
    while (my $rdirEntry = readdir($rdir))
642
    {
643
        #   Skip hidden files and directories
644
        next if ($rdirEntry =~ m~^\.~);
645
        my $vdirName = catdir($ReleaseStore, $rdirEntry );
646
        next unless ( -d $vdirName );
647
 
648
        #
649
        #   Process each version within the Release
650
        #
651
        opendir (my $vdir, $vdirName) || Warning ("Cannot open directory: $vdirName", $!);
652
        while (my $vdirEntry = readdir($vdir))
653
        {
654
            #   Skip hidden files and directories
655
            next if ($vdirEntry =~ m~^\.~);
656
            my $ldirName = catdir($vdirName, $vdirEntry );
657
            next unless ( -d $ldirName );
658
 
659
            #
660
            #   Process each entry within the Version
661
            #
662
            opendir (my $ldir, $ldirName) || Warning ("Cannot open directory: $ldirName", $!);
663
            while (my $ldirEntry = readdir($ldir))
664
            {
665
                #   Skip hidden files and directories (also borken symlinks )
666
                next if ($ldirEntry =~ m~^\.~);
667
                my $dirName = catdir($ldirName, $ldirEntry );
668
                next unless ( -d $dirName );
669
 
670
                #
671
                #   Process each entry within the Version
672
                #
673
                my $pkgName = $ldirEntry;
674
                if (-l $dirName)
675
                {
676
                    $pkgName = readlink($dirName);
677
                    $pkgName =~ s~.*/~~;
678
                }
679
                $pkgsUsed{$pkgName}++;
680
            }
681
            close ($ldir);
682
        }
683
        close ($vdir);
684
    }
685
    close ($rdir);
686
 
687
    #
688
    #   Process the Packages directory and remove those not currently used
689
    #
690
    #
691
    #   Process each entry within the Version
692
    #
693
    opendir (my $pdir, $PackageStore) || Error ("Cannot open directory: $PackageStore", $!);
694
    while (my $pdirEntry = readdir($pdir))
695
    {
696
        #   Skip hidden files and directories
697
        next if ($pdirEntry =~ m~^\.~);
698
        my $pdirName = catdir($PackageStore, $pdirEntry );
699
        next unless ( -d $pdirName );
700
        next if (exists $pkgsUsed{$pdirEntry} );
701
 
702
        Message("Cleanup: $pdirEntry");
703
        RmDirTree($pdirName);
704
    }
705
    close ($pdir);
706
 
707
    #DebugDumpData("pkgsUsed", \%pkgsUsed);
708
}
709
 
710
 
711
#-------------------------------------------------------------------------------
712
# Function        : getReleaseData 
713
#
714
# Description     : Get all the required Release Data 
715
#
716
# Inputs          :  
717
#
718
# Returns         : 
719
#
720
sub getReleaseData
721
{
722
    my ($rtagid) = @_;
723
    my (@row);
724
 
725
    Information("getReleaseData");
726
    connectRM(\$RM_DB) unless $RM_DB;
727
 
728
 
729
    #
730
    # Determine which Releases need LXR support
731
    #
732
    my $m_sqlstr = 
733
        "SELECT rtag_id, " .
734
        "  rt.proj_id, " .
735
        "  p.PROJ_NAME, " .
736
        "  rtag_name, " .
737
        "  official, " .
738
        "  NVL(TRUNC (SYSDATE - rt.official_stamp),0) AS OFFICIAL_STAMP_DAYS " .
739
        "FROM release_tags rt, " .
740
        "  projects p " .
741
        "WHERE rt.lxr  = 'Y' " .
742
        "AND p.PROJ_ID = rt.proj_id ";
743
 
744
    my $sth = $RM_DB->prepare($m_sqlstr);
745
    if ( defined($sth) )
746
    {
747
        if ( $sth->execute( ) )
748
        {
749
            if ( $sth->rows )
750
            {
751
                while ( @row = $sth->fetchrow_array )
752
                {
753
                    my $rtagid = $row[0];
754
                    my $data;
755
                    $data->{Project} = $row[2];
756
                    $data->{Name} = $row[3];
757
                    $data->{official} = substr($row[4],0,1);
758
                    $data->{official_stamp_days} = $row[5];
759
 
760
                    #
761
                    #   Determine if this request for an LXR release is OK
762
                    #   Ok If the release is Open, CCB or Restricted
763
                    #   Ok if closed and has been closed to < 10 days
764
                    #
765
                    if (index('NRC', $data->{official}) >= 0)
766
                    {
767
                        $data->{LXR} = 1;
768
                    }
769
                    elsif ($data->{official} eq 'Y' && $data->{official_stamp_days} < 10)
770
                    {
771
                        $data->{LXR} = 2;
772
                    }
773
 
774
                    $ReleaseData{$rtagid}{release} = $data;
775
                }
776
            }
777
            $sth->finish();
778
        }
779
    }
780
    else
781
    {
782
        Error("getReleaseData:Prepare failure" );
783
    }
784
 
785
    DebugDumpData("ReleaseData", \%ReleaseData);
786
    foreach my $rtagid ( keys %ReleaseData)
787
    {
788
        next unless $ReleaseData{$rtagid}{release}{LXR};
789
        Information("Entry: RtagId $rtagid");
790
        getOneRelease($rtagid);
791
    }
792
}
793
 
794
#-------------------------------------------------------------------------------
795
# Function        : getOneRelease
796
#
797
# Description     : Get data for one Release
798
#
799
# Inputs          : rtagid
800
#
801
# Returns         : 
802
#
803
sub getOneRelease
804
{
805
    my ($rtagid) = @_;
806
    my (@row);
807
 
808
    connectRM(\$RM_DB) unless $RM_DB;
809
 
810
 
811
    # Get details for each package in the Release
812
    #   Don't worry about dependent packages
813
    #
814
    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)".
815
                   " FROM RELEASE_MANAGER.RELEASE_CONTENT rc, RELEASE_MANAGER.PACKAGE_VERSIONS pv, RELEASE_MANAGER.PACKAGES pkg" .
816
                   " WHERE rc.RTAG_ID = $rtagid AND rc.PV_ID = pv.PV_ID AND pv.PKG_ID = pkg.PKG_ID";
817
    my $sth = $RM_DB->prepare($m_sqlstr);
818
    if ( defined($sth) )
819
    {
820
        if ( $sth->execute( ) )
821
        {
822
            if ( $sth->rows )
823
            {
824
                while ( @row = $sth->fetchrow_array )
825
                {
826
                    my $data;
827
                    my $pvid = $row[0];
828
                    unless (exists $Packages{$pvid}) {
829
                        $data->{pv_id} = $row[0];
830
                        $data->{name} = $row[1];
831
                        $data->{ver} = $row[2];
832
                        $data->{ext} = $row[3] || '';
833
                        $data->{vcs} = $row[4] || '';
834
                        $Packages{$pvid} = $data;
835
                    }
836
                    my $rdata;
837
                    $rdata->{required} = 1;
838
                    $ReleaseData{$rtagid}{data}{$pvid} = $rdata;
839
                }
840
            }
841
            $sth->finish();
842
        }
843
    }
844
    else
845
    {
846
        Error("getOneRelease:Prepare failure" );
847
    }
848
}
849
 
850
#-------------------------------------------------------------------------------
851
# Function        : genDatabaseName 
852
#
853
# Description     : Genertate the name of a database
854
#
855
# Inputs          : rtag_id 
856
#
857
# Returns         : Text Name of the database
858
#
859
 
860
sub genDatabaseName
861
{
862
    my ($rtag_id) = @_;
863
    return 'LXR_' . $rtag_id;
864
}
865
 
866
#-------------------------------------------------------------------------------
867
# Function        : readConfig 
868
#
869
# Description     : Read the basic LXR config
870
#                   This is held in a Perl structure 
871
#
872
# Inputs          : None 
873
#
874
# Returns         : Populate Global Data
875
#
876
sub readConfig
877
{
878
    my $cfile = catfile($scriptDir,'jats_lxr.conf');
879
    Error ("Expected config file not found: $cfile") unless ( -f $cfile );
880
    require $cfile;
881
 
882
#   #
883
#   #   Create data
884
#   #
885
#   my %hash = (
886
#   number => 42,
887
#   string => 'This is a string',
888
#   array  => [ 1 .. 10 ],
889
#   hash   => { apple => 'red', banana => 'yellow' },
890
#   );
891
#
892
#   # Print structure to file
893
#   open (my $out, '>', $cfile) || Error("Can't create $cfile. $!");
894
#   DebugDumpData("Hash", \%hash);
895
#   print {$out} Data::Dumper->Dump([\%hash], ['$config']);
896
#   close $out;
897
 
898
    #DebugDumpData("config", \$config);
899
 
900
}
901
 
902
#-------------------------------------------------------------------------------
903
# Function        : startLogFile 
904
#
905
# Description     : Start logging to a log file
906
#                   Generate a nice name for the log file
907
#
908
# Inputs          : 
909
#
910
# Returns         : 
911
#
912
sub startLogFile
913
{
914
    if ( $opt_logfile )
915
    {
916
        if (exists $config->{lxrLogDir})
917
        {
918
            my ($sec,$min,$hour,$mday,$mon,$year,$wday,$yday,$isdst) = gmtime($stamptime);
919
            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);
920
            $name = catdir($config->{lxrLogDir}, $name);
921
 
922
            mkpath($config->{lxrLogDir}); 
923
            if (-d $config->{lxrLogDir} )
924
            {
925
                open STDOUT, '>', $name  or die "Can't redirect STDOUT: $!";
926
                open STDERR, ">&STDOUT"  or die "Can't dup STDOUT: $!";
927
            }
928
            else
929
            {
930
                Warning("Can't create log dir: $config->{lxrLogDir}. $!");
931
            }
932
        }
933
    }
934
}
935
 
936
#-------------------------------------------------------------------------------
937
# Function        : cleanupLogFiles 
938
#
939
# Description     : Remove old log files
940
#
941
# Inputs          : 
942
#
943
# Returns         : 
944
#
945
sub cleanupLogFiles
946
{
947
    if (exists $config->{lxrLogDir} && exists $config->{logAge}  && $config->{logAge} > 0 )
948
    {
949
        Verbose("cleanupLogFiles:$config->{lxrLogDir}, $config->{logAge}");
950
        if ( opendir my $logDir, $config->{lxrLogDir} )
951
        {
952
            foreach my $fileName (readdir $logDir)
953
            {
954
                my $file = catfile($config->{lxrLogDir}, $fileName);
955
                next unless -f $file;
956
                next unless -M $file > $config->{logAge};
957
                Verbose("Purge logfile: $fileName");
958
                unlink $file;
959
            }
960
            closedir $logDir;
961
        }
962
    }
963
}
964
 
965
 
966
#-------------------------------------------------------------------------------
967
#   Documentation
968
#
969
 
970
=pod
971
 
972
=head1 NAME
973
 
974
jats_lxr - Maintain LXR Releases
975
 
976
=head1 SYNOPSIS
977
 
978
  jats jats_lxr [options]
979
 
980
 Options:
981
    -help               - brief help message
982
    -help -help         - Detailed help message
983
    -man                - Full documentation
984
    -[no]createVersions - Create new versions. Default:Create
985
    -[no]extract        - Extract source code. Default:Extract
986
    -[no]index          - Index new LXR versions. Default:Index
987
    -[no]purge          - Purge unused packages. Default:Purge
988
    -[no]logfile        - Capture out to a log file. Default:Log
989
 
990
=head1 OPTIONS
991
 
992
=over 8
993
 
994
=item B<-help>
995
 
996
Print a brief help message and exits.
997
 
998
=item B<-help -help>
999
 
1000
Print a detailed help message with an explanation for each option.
1001
 
1002
=item B<-man>
1003
 
1004
Prints the manual page and exits.
1005
 
1006
=item B<-verbose>
1007
 
1008
This option will display progress information as the program executes.
1009
 
1010
=item B<-[no]createVersions>
1011
 
1012
This option can be used to suppress the creation of new views.
1013
 
1014
=item B<-[no]extract>
1015
 
1016
This option can be used to suppress the extraction of source.
1017
 
1018
=item B<-[no]index>
1019
 
1020
This option can be used to suppress the indexing of newly created views.
1021
 
1022
=item B<-[no]purge>
1023
 
1024
This option can be used to suppress purging of packages that are no longer used by any of the LXR Trees.
1025
 
1026
=back
1027
 
1028
=head1 DESCRIPTION
1029
 
1030
This program is a tool for creating and maintaining an LXR instance within the VIX Build System.
1031
 
1032
The program can:
1033
 
1034
=over 8
1035
 
1036
=item * 
1037
 
1038
Examine the Release Manager Database and determine which Releases are a part of the set to have LXR Views created.
1039
 
1040
Releases that are Open (or Restricted or in CCB Mode) or that have been closed for less than 10 days will be processed.
1041
 
1042
=item *
1043
 
1044
Examine the Release Manager Database and determine the package-versions that are a part of the LXR Release Set.
1045
 
1046
The process will only examine the contents of a Release. It will not descend the version dependency tree.
1047
 
1048
The program will then extract new package-versions into it's Package Store. Multiple LXR Tree's will share the one 
1049
instance of the extracted source code.
1050
 
1051
=item *
1052
 
1053
Create a new 'Version' for each Release.
1054
 
1055
The Version Name is based on the date-time at which the process is run.
1056
 
1057
Each Version is a symlink to the required package-version held in the Package Store.
1058
 
1059
This step can be suppressed though a command line option.
1060
 
1061
=item *
1062
 
1063
Remove unused LXR Trees (Releases no longer being processed) and unused Versions within each Tree.
1064
 
1065
Releases that are no longer eligable for processing will be retained for 10 days and then deleted. 
1066
During this time the existing versions will not be aged out.
1067
 
1068
At the moment this tool simply retains the last 5 Versions of each Release. If the tool 
1069
is run nightly then this will translate into  5 days.
1070
 
1071
=item *
1072
 
1073
Regenerate the LXR Configuration file
1074
 
1075
Create new database tables for new Releases
1076
 
1077
=item *
1078
 
1079
Run the LXR indexer for each LXR Version that has not been processed. Once processed the Version will 
1080
be tagged to prevent further indexing.
1081
 
1082
=item *
1083
 
1084
Remove unused Package-Versions from the Package Store.
1085
 
1086
=back
1087
 
1088
=cut
1089