Subversion Repositories DevTools

Rev

Rev 1044 | Go to most recent revision | Details | Last modification | View Log | RSS feed

Rev Author Line No. Line
1040 dpurdie 1
#! /usr/bin/perl
2
########################################################################
3
# Copyright (C) 2011 Vix-ERG Limited, All rights reserved
4
#
5
# Module name   : blatPopulate
6
# Compiler(s)   : Perl
7
#
8
# Description   : Populate the blat tags directories with RM data
9
#
10
#......................................................................#
11
 
12
require 5.008_002;
13
use strict;
14
use warnings;
15
 
16
use Getopt::Long;                               # Option processing
17
use Pod::Usage;                                 # Required for help support
18
 
19
use File::Basename;
20
use File::Spec::Functions qw(catfile);
21
use FindBin;
22
 
23
use FindBin;                                    # Determine the current directory
24
use lib "$FindBin::Bin/lib";                    # Allow local libraries
25
use Utils;
26
use Logger;
27
 
28
use Data::Dumper;
29
 
30
#
31
#   Globals
32
#
33
my $rootDir = $FindBin::Bin;
34
my $configPath = "config/blatPopulate.cfg";
35
my $conf;
36
my $errors;
37
my $logger;
38
my @args;
39
 
40
#
41
#   Options
42
#
43
my $opt_help = 0;
44
my $opt_verbose = 0;
45
 
46
my $opt_pname;
47
my $opt_pver;
48
my $opt_rtag_id;
49
my $opt_pkg_id;
50
my $opt_pv_id;
51
my $opt_proj_id;
52
my $opt_tagdir = 'tags';
53
 
54
 
55
#
56
#   Describe config uration parameters
57
#
58
my %cdata = (
59
    'logfile'         => {'mandatory' => 1    , 'fmt' => 'vfile'},
60
    'logfile.size'    => {'default' => '1M'   , 'fmt' => 'size'},
61
    'logfile.count'   => {'default' => 9      , 'fmt' => 'int'},
62
    'verbose'         => {'default' => 0      , 'fmt' => 'int'},
63
    'tagdir'          => {'mandatory' => 1    , 'fmt' => 'dir'},
64
    'maxFileAge'      => {'default' => '1h'   , 'fmt' => 'period'},
65
);
66
 
67
#-------------------------------------------------------------------------------
68
# Function        : Mainline Entry Point
69
#
70
# Description     :
71
#
72
# Inputs          :
73
#
74
@args = @ARGV;
75
my $result = GetOptions (
76
                "help|h:+"      => \$opt_help,
77
                "manual:3"      => \$opt_help,
78
                "verbose:+"     => \$opt_verbose,
79
                "tagdir=s"      => \$opt_tagdir,
80
 
81
                "pname=s"       => \$opt_pname,
82
                "pver=s"        => \$opt_pver,
83
                "rtag_id=s"     => \$opt_rtag_id,
84
                "pkg_id=s"      => \$opt_pkg_id,
85
                "pv_id=s"       => \$opt_pv_id,
86
                "proj_id=s"     => \$opt_proj_id,
87
 
88
                );
89
 
90
                #
91
                #   UPDATE THE DOCUMENTATION AT THE END OF THIS FILE !!!
92
                #
93
 
94
#
95
#   Process help and manual options
96
#
97
pod2usage(-verbose => 0, -message => "blatPopulate") if ($opt_help == 1 || ! $result || $#ARGV >= 0);
98
pod2usage(-verbose => 1) if ($opt_help == 2 );
99
pod2usage(-verbose => 2) if ($opt_help > 2);
100
 
101
#
102
#   Set the CWWD as the directory of the script
103
#   This simplifies configuration and use
104
#
105
chdir ($rootDir) || die ("Cannot 'cd' to $rootDir: $!\n");
106
 
107
#
108
#   Read in config
109
#
110
($conf, $errors) = Utils::readconf ( $configPath, \%cdata );
111
if ( scalar @{$errors} > 0 )
112
{
113
    warn "$_\n" foreach (@{$errors});
114
    die ("Config contained errors\n");
115
}
116
 
117
$conf->{verbose} = $opt_verbose if ( $opt_verbose > 0 );
118
$logger = Logger->new($conf);
119
$conf->{logger} = $logger;
120
$logger->verbose2("Args: @args");
121
 
122
#
123
#   Sanity Test
124
#
125
$logger->err ("pname not provided")    unless ( $opt_pname );
126
$logger->err ("pver not provided")     unless ( $opt_pver );
127
$logger->err ("rtag_id not provided")  unless ( $opt_rtag_id );
128
$logger->err ("pkg_id not provided")   unless ( $opt_pkg_id );
129
$logger->err ("pv_id not provided")    unless ( $opt_pv_id );
130
$logger->err ("proj_id not provided")  unless ( $opt_proj_id );
131
 
132
#
133
#   Examine all the tag subdirectories
134
#   They will have a configuration file in them that has been created by the
135
#   consumer daemon.
136
#
137
 
138
    my $dh;
139
    unless (opendir($dh, $opt_tagdir) )
140
    {
141
        $logger->err ("Can't opendir $opt_tagdir: $!");
142
    }
143
 
144
    #
145
    #   Process each entry
146
    #       Ignore those that start with a .
147
    #       Only process subdirs
148
    #
149
    while (my $tag = readdir($dh) )
150
    {
151
        next if ( $tag =~ m~^\.~ );
152
        my $tagfile = catfile($opt_tagdir, $tag, '.config');
153
        next unless ( -f $tagfile );
154
        $logger->verbose2 ("Tag Dir: $tagfile");
155
 
156
        my ($mtime) = Utils::mtime($tagfile);
157
        my $age = time() - $mtime;
158
        $logger->verbose3( "Config File Age: $age, $conf->{maxFileAge}");
159
        if ( $age > $conf->{maxFileAge} )
160
        {
161
            $logger->verbose ("File is OLD: $tagfile, $age");
162
            unlink $tagfile;
163
            next;
164
        }
165
 
166
        #
167
        #   Read in the config file
168
        #   Items of interest are:
169
        #       project
170
        #       release
171
        #       pkg.Name
172
        #
173
        my $data = ConfigReader::readConfig($tagfile);
174
        if ( $data )
175
        {
176
#print Dumper($data);
177
            if (   exists $data->{projects}{$opt_proj_id}
178
                || exists $data->{releases}{$opt_rtag_id}
179
                || exists $data->{pkg}{$opt_pname} )
180
                {
181
                    TouchFile( catfile( $opt_tagdir, $tag, $opt_pname . '::' . $opt_pver ));
182
                }
183
        }
184
    }
185
    closedir $dh;
186
 
187
#-------------------------------------------------------------------------------
188
# Function        : TouchFile 
189
#
190
# Description     : touch a file
191
#                   Real use is to touch a marker file
192
#
193
# Inputs          : path        - path to the file
194
#
195
# Returns         : TRUE if an error occured in creating the file
196
#
197
sub TouchFile
198
{
199
    my ($path) = @_;
200
    my $result = 0;
201
    my $tfh;
202
    $logger->verbose( "Touching: $path" );
203
    if ( ! -f $path )
204
    {
205
        open ($tfh, ">>", $path) || ($result = 1);
206
        close $tfh;
207
    }
208
    else
209
    {
210
 
211
        #
212
        #   Modify the file
213
        #
214
        #   Need to physically modify the file
215
        #   Need to change the 'change time' on the file. Simply setting the
216
        #   last-mod and last-access is not enough to get past WIN32
217
        #   OR 'utime()' does not work as expected
218
        #
219
        #   Read in the first character of the file, rewind and write it
220
        #   out again.
221
        #
222
        my $data;
223
        open ($tfh , "+<", $path ) || return 1;
224
        if ( read ( $tfh, $data, 1 ) )
225
        {
226
            seek  ( $tfh, 0, 0 );
227
            print $tfh $data;
228
        }
229
        else
230
        {
231
            #
232
            #   File must have been of zero length
233
            #   Delete the file and create it
234
            #
235
            close ($tfh);
236
            unlink ( $path );
237
            open ($tfh, ">>", $path) || ($result = 1);
238
        }
239
        close ($tfh);
240
    }
241
    return $result;
242
}
243
 
244
package ConfigReader;
245
our %config;
246
 
247
#-------------------------------------------------------------------------------
248
# Function        : readConfig
249
#
250
# Description     : Read in a configuration file
251
#                   The file is a perl data structure and it can be
252
#                   required directly
253
#
254
# Inputs          : $fname              - Name of the file to read
255
#
256
# Returns         : Data component of the file
257
#
258
sub readConfig
259
{
260
    my ($fname) = @_;
261
#print "Reading: $fname\n";
262
    require $fname;
263
    return \%config;
264
}
265
 
266
#-------------------------------------------------------------------------------
267
#   Documentation
268
#
269
 
270
=pod
271
 
272
=head1 NAME
273
 
274
blatPopulate - Populate Blats tags directory to provide fast-transfer of packages
275
 
276
=head1 SYNOPSIS
277
 
278
blatPopulate ...
279
 
280
 
281
 Options:
282
    -help              - brief help message
283
    -help -help        - Detailed help message
284
    -man               - Full documentation
285
    -verbose           - A little bit of logging
286
    -tagdir=path       - Specify alternate tag base
287
    -...               - Package data
288
 
289
=head1 OPTIONS
290
 
291
=over 8
292
 
293
=item B<-help>
294
 
295
Print a brief help message and exits.
296
 
297
=item B<-help -help>
298
 
299
Print a detailed help message with an explanation for each option.
300
 
301
=item B<-man>
302
 
303
Prints the manual page and exits.
304
 
305
=item B<-tagdir=path>
306
 
307
This provides an alternate tag directory root. The default value is a 'tags'
308
directory located below the directory in which the program is located.
309
 
310
=back
311
 
312
=head1 DESCRIPTION
313
 
314
This utility is designed to be invoked by Release Manager when a new package
315
has been added to a release.
316
 
317
The function of this program is to determine which Blat transfer targets
318
need to be notified of this event. This is done by
319
 
320
=over 8
321
 
322
=item * Scanning all tag directories for a .config file
323
 
324
=item * Examining the .config file and if the transfer target needs the current
325
        package then a tag file will be created.
326
 
327
=back
328
 
329
The .config file is created by the the consume BlatDaemon on a regular basis.
330
If the file is too old it will be deleted, on the assumption that the
331
blatDaemon is dead.
332
 
333
=cut
334