Subversion Repositories DevTools

Rev

Rev 7406 | Details | Compare with Previous | Last modification | View Log | RSS feed

Rev Author Line No. Line
7387 dpurdie 1
#! /usr/bin/perl
2
########################################################################
3
# COPYRIGHT - VIX IP PTY LTD ("VIX"). ALL RIGHTS RESERVED.
4
#
5
# Module name   : blatTarZip.pl
6
# Module type   :
7
# Compiler(s)   : Perl
8
# Environment(s):
9
#
10
# Description   :   This is a blat related task that will monitor a
11
#                   directory for requests to tarZip a package
12
#
13
# Usage         :   ARGV[0] - Path to config file for this instance
14
#
15
#......................................................................#
16
 
17
require 5.008_002;
18
use strict;
19
use warnings;
20
use Getopt::Long;
21
use File::Basename;
22
use Data::Dumper;
23
use File::Spec::Functions;
24
use POSIX ":sys_wait_h";
25
use File::Temp qw/tempfile/;
26
use Digest::MD5;
27
 
28
use FindBin;                                    # Determine the current directory
29
use lib "$FindBin::Bin/lib";                    # Allow local libraries
30
 
31
use Utils;
32
use StdLogger;                                  # Log to sdtout
33
use Logger;                                     # Log to file
34
 
35
#
36
#   Database interface
37
#   Pinched from jats and modified so that this software is not dependent on JATS
38
#
39
use IO::Handle;
40
use JatsRmApi;
41
use DBI;
42
 
43
#
44
#   Globals
45
#
46
my $logger = StdLogger->new();                  # Stdout logger. Only during config
47
$logger->err("No config file specified") unless (defined $ARGV[0]);
48
$logger->err("Config File does not exist: $ARGV[0]") unless (-f $ARGV[0]);
49
my $name = basename( $ARGV[0]);
50
   $name =~ s~.conf$~~;
51
my $now = 0;
52
my $startTime = 0;
53
my $tagDirTime = 0;
54
my $lastDirScan = 0;
55
my $lastCleanScan =  0;
56
my $mtimeConfig = 0;
57
my $conf;
58
my $yday = -1;
59
my $tagRoot;
60
 
61
#
62
#   Contain statisics maintained while operating
63
#       Can be dumped with a kill -USR2
64
#       List here for documentation
65
#  
66
 
67
my %statistics = (
68
    SeqNum => 0,                        # Bumped when $statistics are dumped
69
    timeStamp => 0,                     # DateTime when statistics are dumped
70
    upTime => 0,                        # Seconds since program start
71
    Cycle => 0,                         # Major process loop counter
72
    phase => 'Init',                    # Current phase of operation
73
    state => 'OK',                      # Nagios state
74
                                        # 
75
                                        # The following are reset each day
76
    dayStart => 0,                      # DateTime when daily data was reset
77
    txCount => 0,                       # Packages Transferred
78
    delCount => 0,                      # Packages marked for deletion
79
    staleTags => 0,                     # Stale Tags
80
    linkErrors => 0,                    # Transfer (zip) errors
81
                                        # 
82
                                        # Per Cycle Data - Calculated each processing Cycle
83
    total    => 0,                      # Packages to be synced
84
    delete   => 0,                      # Packages to delete
85
    excluded => 0,                      # Packages excluded    
86
    filtered => 0,                      # Packages filtered out
87
    missing  => 0,                      # Packages missing
88
    transfer => 0,                      # Packages to transfer
89
    writable => 0,                      # Packages still writable - thus not transferred
90
    tagCount => 0,                      # Packages tagged to be transferred
91
                                        #
92
);
93
 
94
#
95
#   Describe configuration parameters
96
#
97
my %cdata = (
98
    'piddir'          => {'mandatory' => 1      , 'fmt' => 'dir'},
99
    'sleep'           => {'default'   => 5      , 'fmt' => 'period'},
100
    'dpkg_archive'    => {'mandatory' => 1      , 'fmt' => 'dir'},
101
    'logfile'         => {'mandatory' => 1      , 'fmt' => 'vfile'},
102
    'logfile.size'    => {'default'   => '1M'   , 'fmt' => 'size'},
103
    'logfile.count'   => {'default'   => 9      , 'fmt' => 'int'},
104
    'verbose'         => {'default'   => 0      , 'fmt' => 'int'},
105
    'active'          => {'default'   => 1      , 'fmt' => 'bool'},
106
    'debug'           => {'default'   => 0      , 'fmt' => 'bool'},                 # Log to screen
7397 dpurdie 107
    'txdetail'        => {'default'   => 0      , 'fmt' => 'bool'},
108
    'tagdir'          => {'mandatory' => 1      , 'fmt' => 'mkdir'},
7387 dpurdie 109
    'forcedirscan'    => {'default'   => 100    , 'fmt' => 'period'},
110
    'tagMaxPackages'  => {'default'   => 10     , 'fmt' => 'int'},
111
    'tagage'          => {'default'   => '10d'  , 'fmt' => 'period'},
112
    'cleanPeriod'     => {'default'   => '30m'  , 'fmt' => 'period'},
7389 dpurdie 113
    'maxFileAge'      => {'default'   => '24h'  , 'fmt' => 'period'},
7387 dpurdie 114
);
115
 
116
 
117
#
118
#   Read in the configuration
119
#       Set up a logger
120
#       Write a pidfile - thats not used
121
$now = $startTime = time();
122
readConfig();
123
Utils::writepid($conf);
124
$logger->logmsg("Starting...");
125
readStatistics();
7423 dpurdie 126
sighandlers();
7387 dpurdie 127
 
128
#
129
#   Main processing loop
130
#   Will exit when terminated by parent
131
#
132
while (1)
133
{
134
    $logger->verbose3("Processing");
135
    $statistics{Cycle}++;
136
    $now = time();
137
 
138
    $statistics{phase} = 'ReadConfig';
139
    readConfig();
140
    if ( $conf->{'active'} )
141
    {
142
        $statistics{phase} = 'Monitor Tags';
143
        processRequests();
144
        cleanZipStore();
145
    }
146
 
147
    $statistics{phase} = 'Sleep';
148
    sleep( $conf->{'sleep'} );
149
    reapChildren();
150
 
151
    #   If my PID file ceases to be, then exit the daemon
152
    #   Used to force daemon to restart
153
    #
154
    unless ( -f $conf->{'pidfile'} )
155
    {
156
        $logger->logmsg("Terminate. Pid file removed");
157
        last;
158
    }
159
}
160
$statistics{phase} = 'Terminated';
161
$logger->logmsg("Child End");
162
exit 0;
163
 
164
#-------------------------------------------------------------------------------
165
# Function        : reapChildren 
166
#
167
# Description     : Reap any and all dead children
168
#                   Call in major loops to prevent zombies accumulating 
169
#
170
# Inputs          : None
171
#
172
# Returns         : 
173
#
174
sub reapChildren
175
{
176
    my $currentPhase = $statistics{phase};
177
    $statistics{phase} = 'Reaping';
178
 
179
    my $kid;
180
    do {
181
        $kid = waitpid(-1, WNOHANG);
182
    } while ( $kid > 0 );
183
 
184
    $statistics{phase} = $currentPhase;
185
}
186
 
187
 
188
#-------------------------------------------------------------------------------
189
# Function        : readConfig
190
#
191
# Description     : Re read the config file if it modification time has changed
192
#
193
# Inputs          : Nothing
194
#
195
# Returns         : 0       - Config not read
196
#                   1       - Config read
197
#                             Config file has changed
198
#
199
sub readConfig
200
{
201
    my ($mtime) = Utils::mtime($ARGV[0]);
202
    my $rv = 0;
203
 
204
    if ( $mtimeConfig != $mtime )
205
    {
206
        $logger->logmsg("Reading config file: $ARGV[0]");
207
        $mtimeConfig = $mtime;
208
        my $errors;
209
        ($conf, $errors) = Utils::readconf ( $ARGV[0], \%cdata );
210
        if ( scalar @{$errors} > 0 )
211
        {
212
            warn "$_\n" foreach (@{$errors});
213
            die ("Config contained errors\n");
214
        }
215
 
216
        #
217
        #   Reset some information
218
        #   Create a new logger
219
        #
220
        $logger = Logger->new($conf) unless $conf->{debug};
221
        $conf->{logger} = $logger;
222
        $conf->{'pidfile'} = $conf->{'piddir'} . '/' . $name . '.pid';
223
        $logger->setVerbose($conf->{verbose});
224
        $logger->verbose("Log Levl: $conf->{verbose}");
225
 
226
        #
227
        #   Setup statistics filename
228
        $conf->{'statsfile'} = $conf->{'piddir'} . '/' . $name . '.stats';
229
        $conf->{'statsfiletmp'} = $conf->{'piddir'} . '/' . $name . '.stats.tmp';
230
 
231
        #
232
        #   Calculate the base of the tags directory
233
        #   ASSUME all tagdirs are in the same tree as my tags dir
234
        #
235
        $conf->{'tagdir'} =~ m~^(.*)/~;
236
        $tagRoot = $1;
237
    }
238
 
239
    #
240
    #   When config is read force some actions
241
 
242
#Utils::DebugDumpData ("Config", $conf);
243
 
244
    $logger->warn("Tar Zip is inactive") unless ( $conf->{'active'} );
245
    return $rv;
246
}
247
 
248
 
249
#-------------------------------------------------------------------------------
250
# Function        : processRequests
251
#
252
# Description     : Process tags and generate tarZip files as required
253
#                       Determine if new tags are present
254
#                       Process each tag
255
#
256
# Inputs          : None
257
#
258
# Returns         : Nothing
259
#
260
sub processRequests
261
{
262
    #
263
    #   Determine if new tags are present by examining the time
264
    #   that the directory was last modified.
265
    #
266
    #   Allow for a forced scan to catch packages that did not transfer
267
    #   on the first attempt
268
    #
269
    my $tagCount = 0;
270
    my ($mtime) = Utils::mtime($conf->{'tagdir'} );
271
    if ( ($mtime > $tagDirTime) || ($now > ($lastDirScan + $conf->{'forcedirscan'})) )
272
    {
273
        $logger->verbose2("processTags: ,$conf->{'tagdir'}");
274
        $tagDirTime = $mtime;
275
        $lastDirScan = $now;
276
        my $txcount = $conf->{'tagMaxPackages'};
277
 
278
 
279
        my $dh;
280
        unless (opendir($dh, $conf->{'tagdir'}))
281
        {
282
            $logger->warn ("can't opendir $conf->{'tagdir'}: $!");
283
            return;
284
        }
285
 
286
        #
287
        #   Process each entry
288
        #   Ignore those that start with a .
289
        #
290
        my %tagPkgList;
291
        while (my $tag = readdir($dh) )
292
        {
293
            next if ( $tag =~ m~^\.~ );
294
            my $file = "$conf->{'tagdir'}/$tag";
295
            $logger->verbose3("processTags: $file");
296
 
297
            if ( $tag =~ m~(.+)::(.+)~  )
298
            {
299
                my $package = $1;
300
                my $version = $2;
301
                $tagCount++;
302
                $tagPkgList{$package}{$version} = $file;
303
            }
304
        }
305
        $statistics{tagCount} = $tagCount;
306
        closedir $dh;
307
 
308
        #
309
        #   Process the packages located in the tags area
310
        #
311
        send_tags:
312
        while ( (my ($package, $pvers)) = each %{tagPkgList} )
313
        {
314
            while ( (my ($version, $file) ) = each %{$pvers} )
315
            {
316
                if ( --$txcount <= 0 )
317
                {
318
                    $logger->warn("Max tag transfer count exceeded: $tagCount transfer remaining");
319
                    $tagDirTime = 0;
320
                    last send_tags;
321
                }
322
 
323
                if ( readConfig() )
324
                {
325
                    $logger->warn("Config file changed");
326
                    $txcount = 0;
327
                    $tagDirTime = 0;
328
                    last send_tags;
329
                }
330
 
331
                #
332
                #
7394 dpurdie 333
                if ( ! zipRequestNeeded($package, $version) ) {
334
                    $logger->verbose2("NoZip request outstanding: $package, $version");
7387 dpurdie 335
                    unlink $file;
7394 dpurdie 336
 
337
                } elsif ( tarZipPackage( $package, $version )) {
338
                    unlink $file;
7387 dpurdie 339
                    triggerTransfers($package, $version);
340
                }
341
                else
342
                {
343
                    if ($conf->{'tagage'} > 0) {
344
                        my ($mtime) = Utils::mtime( $file );
345
                        if ( $now - $mtime > $conf->{'tagage'} )
346
                        {
347
                            $logger->warn ("Delete unsatisfied tag: $package::$version after $conf->{'tagage'}" );
348
                            unlink $file;
349
                            $statistics{staleTags}++;
350
                        }
351
                    }
352
                }
353
 
354
                $tagCount--;
355
                reapChildren();
356
            }
357
        }
358
    }
359
}
360
 
361
#-------------------------------------------------------------------------------
7394 dpurdie 362
# Function        : zipRequestNeeded 
363
#
364
# Description     : Scan tags and ensure that the zip request is still needed
365
#                   Another task must still have need for this package to be
366
#                   tarZipped
367
#
368
# Inputs          : $pname
369
#                   $version 
370
#
371
# Returns         : True if still needed 
372
#
373
sub zipRequestNeeded {
374
    my ($pname, $version) = @_;
375
 
376
    #
377
    #   Find the tag in all blat transfer areas
378
    #   
379
    my $tag = "$pname::$version";
380
    my @tagList = glob ("$tagRoot/*/$tag");
381
 
382
    #
383
    #   Expect to find my own tag, so a count of 1 indicates not found elsewhere
384
    # 
385
    my $count = scalar @tagList;
386
    return $count > 1;   
387
}
388
 
389
 
390
#-------------------------------------------------------------------------------
7387 dpurdie 391
# Function        : cleanZipStore  
392
#
393
# Description     : Cleanup the store of zipped packages
394
#                   If a tarZip is no longer needed for a transfer, then we can consider
395
#                   removing it from the store
396
#                   
397
#                   May want to keep it for some time, but ...
398
#                   
399
#                   May need to remove them if they are too old.
400
#                   When a connection is wedged, then we may end up with a lot of packages
401
#                   May be that the ssh tx process will age out old tags, but I don't think so 
402
#                   
403
#                   Should be run periodically
404
#
405
# Inputs          : 
406
#
407
# Returns         : 
408
#
409
sub cleanZipStore
410
{
411
    if ( $conf->{cleanPeriod} == 0 )
412
    {
413
        $logger->verbose2("cleanZipStore disabled");
414
        return;
415
    }
416
 
417
    #
418
    #   Time to perform the scan
419
    #   Will do at startup and every time period there after
420
    #
421
    return unless ( $now > ($lastCleanScan + $conf->{cleanPeriod} ));
422
    $logger->verbose("cleanZipStore");
423
    $lastCleanScan = $now;
424
 
425
 
426
    my %tagPkgList;
427
    #
7406 dpurdie 428
    #   Process all active tag directories ( these have a .config file )
429
    #   Locate all active tags and create a hash of known tags
7387 dpurdie 430
    #   These are packages that we have queued to be transferred
431
    #
7406 dpurdie 432
    if (opendir(my $dh, $tagRoot) )
433
    {
434
        while (my $tagDir = readdir($dh) )
435
        {
436
            next unless -f catfile($tagRoot, $tagDir, '.config');
437
            $logger->verbose3 ("TagScan: $tagDir");
7387 dpurdie 438
 
7406 dpurdie 439
            my @tagList = glob ("$tagRoot/$tagDir/*::*");
440
            foreach my $entry ( @tagList )
441
            {
442
                $entry =~ m~.*/(.*)::(.*)$~;
443
                $tagPkgList{$1 .'__'.$2 . '.tgz'} = 1;
444
            }
445
        }
446
        closedir $dh;
7387 dpurdie 447
    }
448
 
449
    #
450
    #   Iterate over all the stored tarZips and remove them if they are no longer needed
451
    #
452
    my @tarZipFiles = glob (catfile( $conf->{'dpkg_archive'}, '.dpkg_archive', 'tarStore', '*.tgz' ));
453
    foreach my $entry  (@tarZipFiles) {
454
        $entry =~ m~.*/(.*)$~;
455
        my $fname = $1;
456
 
457
        if (!exists $tagPkgList{$fname}) {
7389 dpurdie 458
 
459
            my ($mtime) = Utils::mtime($entry);
460
            my $age = time() - $mtime;
461
            $logger->verbose3( "File Age: $age, $conf->{maxFileAge}");
462
            if ( $age > $conf->{maxFileAge} ) {
463
                $logger->logmsg("cleanZipStore. Remove: $fname");
464
                unlink $entry;
465
                $logger->warn("cleanZipStore. Cannot Remove: $fname") if (-f $entry);
466
            }
7387 dpurdie 467
        } else {
468
            $logger->verbose("cleanZipStore. Retain: $fname");
469
 
470
        }
471
    }
472
 
473
}
474
 
475
 
476
#-------------------------------------------------------------------------------
477
# Function        : tarZipPackage 
478
#
479
# Description     : Perform the tar Zip operation 
480
#
481
# Inputs          : $pname
482
#                   $version 
483
#
484
# Returns         : 1 - TarZip complete
485
#                   0 - TarZip not complete 
486
#
487
sub tarZipPackage
488
{
489
    my ($pname, $version) = @_;
490
    $logger->logmsg("TarZip $pname $version");
491
 
492
    my $pkgName = $pname .'_'.$version;
493
    my $srcDir = catdir( $conf->{'dpkg_archive'}, $pname, $version);
494
    my $tgtdir = catfile( $conf->{'dpkg_archive'}, '.dpkg_archive', 'tarStore' );
495
    my $zfile = $pname . '__' . $version . '.tgz';
496
    my $tfile = catfile($tgtdir, $zfile);
497
    my $tfileTmp = $tfile . '.TEMP';
7389 dpurdie 498
    my $startTime = time;
7387 dpurdie 499
 
500
    #
501
    #   Does the source exist
502
    if (! -d $srcDir) {
503
        $logger->warn("Package not found: $pname, $version");
504
        return 0;
505
    }
506
 
507
    #
508
    #   If the target zip is already present, then assume the job has been done
509
    #   
510
    if ( -f $tfile ) {
511
        $logger->verbose("tarZipPackage: Already done: $pname, $version");
512
        $logger->verbose2("tarZipPackage: Already done: $pname, $version - $tfile");
513
        return 1;
514
    }
515
 
516
    #
517
    #   Tar zip the file
518
    #       TarZip into a temp file, then rename it
519
    #
520
    my $tar_cmd = "tar -czf $tfileTmp -C  $conf->{'dpkg_archive'} $pname/$version";
521
    $logger->verbose2("tarZipPackage:tar_cmd:$tar_cmd");
522
 
523
    my $ph;
524
    my $cmdRv;
525
    open ($ph, "$tar_cmd |");
526
    while ( <$ph> )
527
    {
528
        chomp;
529
        $logger->verbose2("tarZipPackage:Data: $_");
530
    }
531
    close ($ph);
532
    $cmdRv = $?;
533
    $logger->verbose("tarZipPackage:End: $cmdRv");
534
 
535
    #   Rename the TEMP file, so that the tgz file creation appears atomic
536
    if ($cmdRv eq 0 && -f $tfileTmp) {
537
        rename $tfileTmp, $tfile || $logger->warn("Rename error: $tfileTmp");
538
    }
539
 
7389 dpurdie 540
 
541
    #
542
    #   Display the size of the package (tarZipped)
543
    #       Diagnostic use
544
    #
545
    if ( -f $tfile && $conf->{txdetail}) {
546
        my $tzfsize = -s $tfile; 
547
        my $size = sprintf "%.3f", $tzfsize / 1024 / 1024 / 1024 ;
548
        my $duration = time - $startTime;
549
        $logger->logmsg("tarZipPackage: Stats: $pname, $version, $size Gb, $duration Secs");
550
    }
551
 
552
 
7387 dpurdie 553
    if ( -f $tfile ) {
554
        $statistics{txCount}++;
555
        $logger->verbose2("tarZipPackage:Done: $pname/$version");
556
        $cmdRv = 1;
557
    } else {
558
        unlink $tfileTmp;
559
        $statistics{linkErrors}++;
560
        $logger->verbose2("tarZipPackage:Error: $pname/$version");
561
        $cmdRv = 0;
562
    }
563
 
564
    #
565
    # Return 0 if the required tar file exists
566
    #   
567
    return $cmdRv;
568
}
569
 
570
#-------------------------------------------------------------------------------
571
# Function        : triggerTransfers 
572
#
573
# Description     : Trigger transfers for other blat tasks that may be waiting for this
574
#                   tarZip to have been performed
575
#
576
# Inputs          : $pname
577
#                   $version 
578
#
579
# Returns         : Even less 
580
#
581
sub triggerTransfers
582
{
583
    my ($pname, $version) = @_;
584
 
585
    #
586
    #   Find the tag in all blat transfer areas
587
    #   
588
    my $tag = "$pname::$version";
589
    my @tagList = glob ("$tagRoot/*/$tag");
7389 dpurdie 590
    $logger->verbose2("triggerTransfer: $tagRoot/*/$tag: @tagList");
7387 dpurdie 591
    foreach my $target ( @tagList )
592
    {
593
        $logger->verbose2("triggerTransfer: $target");
594
        $target =~ m~^(.*)/~;
7406 dpurdie 595
        my $tagDir = $1;
596
        my $configFile = catfile($tagDir, '.config');
597
        my $triggerFile = catfile($tagDir, '.trigger');
598
        if ( -f $configFile) {
599
            Utils::TouchFile($conf, $triggerFile);
600
        } else {
601
            unlink $target;
602
        }
7387 dpurdie 603
    }
604
}
605
 
606
#-------------------------------------------------------------------------------
607
# Function        : resetDailyStatistics 
608
#
609
# Description     : Called periodically to reset the daily statistics
610
#
611
# Inputs          : $time       - Current time
612
#
613
# Returns         : 
614
#
615
sub resetDailyStatistics
616
{
617
    my ($time) = @_;
618
 
619
    #
620
    #   Detect a new day
621
    #
622
    my $today = (localtime($time))[7];
623
    if ($yday != $today)
624
    {
625
        $yday = $today;
626
        $logger->logmsg('Resetting daily statistics' );
627
 
628
        # Note: Must match @recoverTags in readStatistics
629
        $statistics{dayStart} = $time;
630
        $statistics{txCount} = 0;
631
        $statistics{delCount} = 0;
632
        $statistics{staleTags} = 0;
633
        $statistics{linkErrors} = 0;
634
    }
635
}
636
 
637
#-------------------------------------------------------------------------------
638
# Function        : readStatistics 
639
#
640
# Description     : Read in the last set of stats
641
#                   Used after a restart to recover daily statistics
642
#
643
# Inputs          : 
644
#
645
# Returns         : 
646
#
647
sub readStatistics
648
{
649
    my @recoverTags = qw(dayStart txCount delCount staleTags linkErrors);
650
 
651
    if ($conf->{'statsfile'} and -f $conf->{'statsfile'})
652
    {
653
        if (open my $fh, $conf->{'statsfile'})
654
        {
655
            while (<$fh>)
656
            {
657
                m~(.*):(.*)~;
658
                if ( grep( /^$1$/, @recoverTags ) ) 
659
                {
660
                    $statistics{$1} = $2;
661
                    $logger->verbose("readStatistics $1, $2");
662
                }
663
            }
664
            close $fh;
665
            $yday = (localtime($statistics{dayStart}))[7];
666
        }
667
    }
668
}
669
 
670
 
671
#-------------------------------------------------------------------------------
672
# Function        : periodicStatistics 
673
#
674
# Description     : Called on a regular basis to write out statistics
675
#                   Used to feed information into Nagios
676
#                   
677
#                   This function is called via an alarm and may be outside the normal
678
#                   processing loop. Don't make assumptions on the value of $now
679
#
680
# Inputs          : 
681
#
682
# Returns         : 
683
#
684
sub periodicStatistics
685
{
686
    #
687
    #   A few local stats
688
    #
689
    $statistics{SeqNum}++;
690
    $statistics{timeStamp} = time();
691
    $statistics{upTime} = $statistics{timeStamp} - $startTime;
692
 
693
    #   Reset daily accumulations - on first use each day
694
    resetDailyStatistics($statistics{timeStamp});
695
 
696
    #
697
    #   Write statistics to a file
698
    #       Write to a tmp file, then rename.
699
    #       Attempt to make the operation atomic - so that the file consumer
700
    #       doesn't get a badly formed file.
701
    #   
702
    if ($conf->{'statsfiletmp'})
703
    {
704
        my $fh;
705
        unless (open ($fh, '>', $conf->{'statsfiletmp'}))
706
        {
707
            $fh = undef;
708
            $logger->warn("Cannot create temp stats file: $!");
709
        }
710
        else
711
        {
712
            foreach my $key ( sort { lc($a) cmp lc($b) } keys %statistics)
713
            {
714
                print $fh $key . ':' . $statistics{$key} . "\n";
715
                $logger->verbose2('Statistics:'. $key . ':' . $statistics{$key});
716
            }
717
            close $fh;
718
 
719
            # Rename temp to real file
720
            rename  $conf->{'statsfiletmp'},  $conf->{'statsfile'} ;
721
        }
722
    }
723
}
724
 
725
#-------------------------------------------------------------------------------
726
# Function        : sighandlers
727
#
728
# Description     : Install signal handlers
729
#
7423 dpurdie 730
# Inputs          : None
7387 dpurdie 731
#
732
# Returns         : Nothing
733
#
734
sub sighandlers
735
{
736
    $SIG{TERM} = sub {
737
        # On shutdown
738
        $logger->logmsg('Received SIGTERM. Shutting down....' );
739
        unlink $conf->{'pidfile'} if (-f $conf->{'pidfile'});
740
        exit 0;
741
    };
742
 
743
    $SIG{HUP} = sub {
744
        # On logrotate
745
        $logger->logmsg('Received SIGHUP.');
746
        $logger->rotatelog();
747
    };
748
 
749
    $SIG{USR1} = sub {
750
        # On Force Cache Clean
751
        $logger->logmsg('Received SIGUSR1.');
752
        $lastCleanScan = 0;
753
    };
754
 
755
    alarm 60;
756
    $SIG{ALRM} = sub {
757
        # On Dump Statistics
758
        $logger->verbose2('Received SIGUSR2.');
759
        periodicStatistics();
760
        alarm 60;
761
    };
762
 
763
    $SIG{__WARN__} = sub { $logger->warn("@_") };
764
    $SIG{__DIE__} = sub { $logger->err("@_") };
765
}
766
 
767
 
768
#-------------------------------------------------------------------------------
769
# Function        : Error, Verbose, Warning
770
#
771
# Description     : Support for JatsRmApi
772
#
773
# Inputs          : Message
774
#
775
# Returns         : Nothing
776
#
777
sub Error
778
{
779
    $logger->err("@_");
780
}
781
 
782
sub Verbose
783
{
784
    $logger->verbose2("@_");
785
}
786
 
787
sub Warning
788
{
789
    $logger->warn("@_");
790
}
791
 
792