1# This file was automatically generated by SWIG (http://www.swig.org).
2# Version 3.0.7
3#
4# Do not make changes to this file unless you know what you are doing--modify
5# the SWIG interface file instead.
6
7package Amanda::Logfile;
8use base qw(Exporter);
9use base qw(DynaLoader);
10require Amanda::Cmdline;
11package Amanda::Logfilec;
12bootstrap Amanda::Logfile;
13package Amanda::Logfile;
14@EXPORT = qw();
15
16# ---------- BASE METHODS -------------
17
18package Amanda::Logfile;
19
20sub TIEHASH {
21    my ($classname,$obj) = @_;
22    return bless $obj, $classname;
23}
24
25sub CLEAR { }
26
27sub FIRSTKEY { }
28
29sub NEXTKEY { }
30
31sub FETCH {
32    my ($self,$field) = @_;
33    my $member_func = "swig_${field}_get";
34    $self->$member_func();
35}
36
37sub STORE {
38    my ($self,$field,$newval) = @_;
39    my $member_func = "swig_${field}_set";
40    $self->$member_func($newval);
41}
42
43sub this {
44    my $ptr = shift;
45    return tied(%$ptr);
46}
47
48
49# ------- FUNCTION WRAPPERS --------
50
51package Amanda::Logfile;
52
53*open_logfile = *Amanda::Logfilec::open_logfile;
54*close_logfile = *Amanda::Logfilec::close_logfile;
55*get_logline = *Amanda::Logfilec::get_logline;
56*log_add = *Amanda::Logfilec::log_add;
57*log_add_full = *Amanda::Logfilec::log_add_full;
58*log_rename = *Amanda::Logfilec::log_rename;
59*find_log = *Amanda::Logfilec::find_log;
60*search_logfile = *Amanda::Logfilec::search_logfile;
61*search_holding_disk = *Amanda::Logfilec::search_holding_disk;
62*dumps_match = *Amanda::Logfilec::dumps_match;
63*dumps_match_dumpspecs = *Amanda::Logfilec::dumps_match_dumpspecs;
64
65############# Class : Amanda::Logfile::find_result_t ##############
66
67package Amanda::Logfile::find_result_t;
68use vars qw(@ISA %OWNER %ITERATORS %BLESSEDMEMBERS);
69@ISA = qw( Amanda::Logfile );
70%OWNER = ();
71%ITERATORS = ();
72sub DESTROY {
73    return unless $_[0]->isa('HASH');
74    my $self = tied(%{$_[0]});
75    return unless defined $self;
76    delete $ITERATORS{$self};
77    if (exists $OWNER{$self}) {
78        Amanda::Logfilec::delete_find_result_t($self);
79        delete $OWNER{$self};
80    }
81}
82
83*swig_timestamp_get = *Amanda::Logfilec::find_result_t_timestamp_get;
84*swig_timestamp_set = *Amanda::Logfilec::find_result_t_timestamp_set;
85*swig_write_timestamp_get = *Amanda::Logfilec::find_result_t_write_timestamp_get;
86*swig_write_timestamp_set = *Amanda::Logfilec::find_result_t_write_timestamp_set;
87*swig_hostname_get = *Amanda::Logfilec::find_result_t_hostname_get;
88*swig_hostname_set = *Amanda::Logfilec::find_result_t_hostname_set;
89*swig_diskname_get = *Amanda::Logfilec::find_result_t_diskname_get;
90*swig_diskname_set = *Amanda::Logfilec::find_result_t_diskname_set;
91*swig_level_get = *Amanda::Logfilec::find_result_t_level_get;
92*swig_level_set = *Amanda::Logfilec::find_result_t_level_set;
93*swig_label_get = *Amanda::Logfilec::find_result_t_label_get;
94*swig_label_set = *Amanda::Logfilec::find_result_t_label_set;
95*swig_filenum_get = *Amanda::Logfilec::find_result_t_filenum_get;
96*swig_filenum_set = *Amanda::Logfilec::find_result_t_filenum_set;
97*swig_status_get = *Amanda::Logfilec::find_result_t_status_get;
98*swig_status_set = *Amanda::Logfilec::find_result_t_status_set;
99*swig_dump_status_get = *Amanda::Logfilec::find_result_t_dump_status_get;
100*swig_dump_status_set = *Amanda::Logfilec::find_result_t_dump_status_set;
101*swig_message_get = *Amanda::Logfilec::find_result_t_message_get;
102*swig_message_set = *Amanda::Logfilec::find_result_t_message_set;
103*swig_partnum_get = *Amanda::Logfilec::find_result_t_partnum_get;
104*swig_partnum_set = *Amanda::Logfilec::find_result_t_partnum_set;
105*swig_totalparts_get = *Amanda::Logfilec::find_result_t_totalparts_get;
106*swig_totalparts_set = *Amanda::Logfilec::find_result_t_totalparts_set;
107*swig_sec_get = *Amanda::Logfilec::find_result_t_sec_get;
108*swig_sec_set = *Amanda::Logfilec::find_result_t_sec_set;
109*swig_bytes_get = *Amanda::Logfilec::find_result_t_bytes_get;
110*swig_bytes_set = *Amanda::Logfilec::find_result_t_bytes_set;
111*swig_kb_get = *Amanda::Logfilec::find_result_t_kb_get;
112*swig_kb_set = *Amanda::Logfilec::find_result_t_kb_set;
113*swig_orig_kb_get = *Amanda::Logfilec::find_result_t_orig_kb_get;
114*swig_orig_kb_set = *Amanda::Logfilec::find_result_t_orig_kb_set;
115sub new {
116    my $pkg = shift;
117    my $self = Amanda::Logfilec::new_find_result_t(@_);
118    bless $self, $pkg if defined($self);
119}
120
121sub DISOWN {
122    my $self = shift;
123    my $ptr = tied(%$self);
124    delete $OWNER{$ptr};
125}
126
127sub ACQUIRE {
128    my $self = shift;
129    my $ptr = tied(%$self);
130    $OWNER{$ptr} = 1;
131}
132
133
134# ------- VARIABLE STUBS --------
135
136package Amanda::Logfile;
137
138*L_BOGUS = *Amanda::Logfilec::L_BOGUS;
139*L_FATAL = *Amanda::Logfilec::L_FATAL;
140*L_ERROR = *Amanda::Logfilec::L_ERROR;
141*L_WARNING = *Amanda::Logfilec::L_WARNING;
142*L_INFO = *Amanda::Logfilec::L_INFO;
143*L_SUMMARY = *Amanda::Logfilec::L_SUMMARY;
144*L_START = *Amanda::Logfilec::L_START;
145*L_FINISH = *Amanda::Logfilec::L_FINISH;
146*L_DISK = *Amanda::Logfilec::L_DISK;
147*L_DONE = *Amanda::Logfilec::L_DONE;
148*L_PART = *Amanda::Logfilec::L_PART;
149*L_PARTPARTIAL = *Amanda::Logfilec::L_PARTPARTIAL;
150*L_SUCCESS = *Amanda::Logfilec::L_SUCCESS;
151*L_PARTIAL = *Amanda::Logfilec::L_PARTIAL;
152*L_FAIL = *Amanda::Logfilec::L_FAIL;
153*L_STRANGE = *Amanda::Logfilec::L_STRANGE;
154*L_CHUNK = *Amanda::Logfilec::L_CHUNK;
155*L_CHUNKSUCCESS = *Amanda::Logfilec::L_CHUNKSUCCESS;
156*L_STATS = *Amanda::Logfilec::L_STATS;
157*L_MARKER = *Amanda::Logfilec::L_MARKER;
158*L_CONT = *Amanda::Logfilec::L_CONT;
159*P_UNKNOWN = *Amanda::Logfilec::P_UNKNOWN;
160*P_PLANNER = *Amanda::Logfilec::P_PLANNER;
161*P_DRIVER = *Amanda::Logfilec::P_DRIVER;
162*P_REPORTER = *Amanda::Logfilec::P_REPORTER;
163*P_DUMPER = *Amanda::Logfilec::P_DUMPER;
164*P_CHUNKER = *Amanda::Logfilec::P_CHUNKER;
165*P_TAPER = *Amanda::Logfilec::P_TAPER;
166*P_AMFLUSH = *Amanda::Logfilec::P_AMFLUSH;
167*P_AMDUMP = *Amanda::Logfilec::P_AMDUMP;
168*P_AMIDXTAPED = *Amanda::Logfilec::P_AMIDXTAPED;
169*P_AMFETCHDUMP = *Amanda::Logfilec::P_AMFETCHDUMP;
170*P_AMCHECKDUMP = *Amanda::Logfilec::P_AMCHECKDUMP;
171*P_AMVAULT = *Amanda::Logfilec::P_AMVAULT;
172*amanda_log_trace_log = *Amanda::Logfilec::amanda_log_trace_log;
173
174@EXPORT_OK = ();
175%EXPORT_TAGS = ();
176
177
178=head1 NAME
179
180Amanda::Logfile - manage Amanda trace logs
181
182=head1 SYNOPSIS
183
184  use Amanda::Logfile qw( :constants );
185  use Amanda::Config qw( :getconf config_dir_relative );
186
187  for my $logfile (Amanda::Logfile::find_log()) {
188    $logfile = config_dir_relative(getconf($CNF_LOGDIR)) . "/" . $logfile;
189
190    my $hdl = Amanda::Logfile::open_logfile($logfile);
191    while (my ($type, $prog, $str) = Amanda::Logfile::get_logline($hdl)) {
192      if ($type == $L_INFO) {
193        my $pname = Amanda::Logfile::program_t_to_string($prog);
194        print "Found info line from $pname: $str\n";
195      }
196    }
197    Amanda::Logfile::close_logfile($hdl);
198
199    my @dumps = Amanda::Logfile::search_logfile("TapeLabel-001", "19780615", $logfile, 1);
200
201    my @matching = Amanda::Logfile::dumps_match([@dumps], "myhost", "/usr", undef, undef, 0);
202    for my $dump (@matching) {
203      print "$dump->{'label'}:$dump->{'filenum'} = $dump->{'hostname'}:$dump->{'disk'}\n";
204    }
205  }
206
207=head1 RAW LOGFILE ACCESS
208
209This section corresponds to the C C<logfile> module.
210
211Raw access to logfiles is accomplished by opening a logfile and
212fetching log lines one by one via the C<get_logline> function.
213
214A log line is represented by a list C<($type, $prog, $string)> where C<$type>
215is one of the C<L_*> constants (available in export tag C<logtype_t>), C<$prog>
216is one of the C<P_*> constants (available in export tag C<program_t>), and
217C<$str> is the remainder of the line. Both sets of constants are also available
218in the usual C<constants> export tag.  Both families of constants can be
219converted to symbolic names with C<logtype_t_to_string> and
220C<program_t_to_string>, respectively.
221
222=head2 FUNCTIONS
223
224Use these functions to read a logfile:
225
226=over
227
228=item C<open_logfile($filename)>
229
230Opens a logfile for reading, returning an opaque log file
231handle. Returns C<undef> and sets C<$!> on failure.
232
233=item C<close_logfile($handle)>
234
235Closes a log file handle.
236
237=item C<get_logline($handle)>
238
239Returns a list as described above representing the next log line in
240C<$handle>, or nothing at the end of the logfile.
241
242=back
243
244=head3 Writing a "current" Logfile
245
246To write a logfile, call C<log_add($logtype, $string)>.  On the first call,
247this function opens and locks C<$logdir/log>; subsequent calls just append to
248this file.  As such, this function is only appropriate for situations where
249C<log_rename> will be invoked later to rename C<$logdir/log> to
250C<$logdir/log.$timestamp.$n>.
251
252If you need to write a log entry for another program, for example to simulate
253taper entries, call C<log_add_full($logtype, $pname, $string)>.
254
255All of the functions in this section can be imported by name if
256desired.
257
258=head3 Utilities
259
260Many trace log entries have a statistics entry in what used to be the error
261message slot, of the form C<[sec .. kb .. kps ..]>.  The function C<make_stats>
262will create such an entry for you:
263
264    make_stats($size, $duration, $orig_kb);
265
266Note that C<$orig_kb> can be undefined, in which case it will not appear in
267the statistics output.
268
269=head2 Amanda::Find::find_result_t objects
270
271These objects contain information about dumps, as read from logfiles.
272Instance variables are:
273
274To rename the current logfile to a datestamped logfile, call C<log_rename($ts)>
275where C<$ts> is the write timestamp for this dump.  The
276C<get_current_log_timestamp()> function will calculate this timestamp,
277returning C<undef> on error.
278
279=over
280
281=item C<timestamp>
282
283=item C<hostname>
284
285=item C<diskname>
286
287=item C<level>
288
289=item C<label>
290
291=item C<filenum>
292
293=item C<status>
294
295=item C<partnum>
296
297=item C<totalparts>
298
299=item C<sec>
300
301=item C<kb>
302
303=back
304
305Note that the format for these variables are based on that found in
306the logfiles.  In particular, C<timestamp> is the timestamp for the run
307in which the client dump took place, and not for the timestamp of the
308logfile.
309
310=head1 HIGHER-LEVEL FUNCTIONS
311
312Functions in this section extract information from logfiles.
313
314=over
315
316=item C<find_log()>
317
318Return a list of logfiles for active tapes.  The tapelist must be loaded
319before this function is called (see L<Amanda::Tapelist>).  This function uses
320the C API which indexes logfiles with tapes.  If there is no corresponding
321tape, the logfile will not be found.
322
323=item C<find_all_logs([dir])>
324
325Return a list of all logs the configuration.  An optional directory argument
326can be specified, if not present, C<find_all_logs> checks C<LOGDIR>.
327
328=item C<find_latest_log([dir])>
329
330Returns the most recent logfile in the list of logfiles returned by
331C<find_all_logs>.  The optional directory argument is passed to
332C<find_all_logs>.
333
334=item C<search_logfile($label, $datestamp, $logfile, $add_missing_disks)>
335
336Return all results in C<$logfile> matching C<$label> and
337C<$datestamp>.  If C<$add_missing_disks> is true, then any disks in
338the logfile not present in the disklist are added to the disklist;
339otherwise, such dumps are skipped.
340
341=item C<search_holding_disk()>
342
343Return results for all holding-disk files.  Results are similar to those from
344search_logfile.
345
346=item C<dumps_match([@results], $hostname, $diskname, $datestamp, $level, $ok)>
347
348Return a filtered version of C<@results> containing only results that
349match the given expressions.  If C<$ok> is true, don't match partial
350results.  Note that C<$level> is given as a string, since it is a
351match expression.
352
353=item C<dumps_match_dumpspecs([@results], [@dumpspecs], $ok)>
354
355Return a filtered version of C<@results>, containing only results that match
356one or more of the dumpspecs.  C<$ok> is as for C<dumps_match>.  Supplying no
357dumpspecs will result in an empty return value.  If multiple dumpspecs match
358the same result, that result will be returned multiple times.
359
360=back
361
362All of these functions can be imported by name.
363
364=head1 DEBUG LOGGING HANDLER
365
366This package provides C<$amanda_log_trace_log>, which sends C<die>
367messages (and any C<g_error> or C<g_critical> calls from C) to the
368trace log.  Use it like this:
369
370  use Amanda::Logfile qw( $amanda_log_trace_log );
371  # ...
372  Amanda::Debug::add_amanda_log_handler($amanda_log_trace_log);
373
374=cut
375
376
377
378push @EXPORT_OK, qw(open_logfile get_logline close_logfile
379    log_add log_add_full);
380
381push @EXPORT_OK, qw(logtype_t_to_string);
382push @{$EXPORT_TAGS{"logtype_t"}}, qw(logtype_t_to_string);
383
384my %_logtype_t_VALUES;
385#Convert an enum value to a single string
386sub logtype_t_to_string {
387    my ($enumval) = @_;
388
389    for my $k (keys %_logtype_t_VALUES) {
390	my $v = $_logtype_t_VALUES{$k};
391
392	#is this a matching flag?
393	if ($enumval == $v) {
394	    return $k;
395	}
396    }
397
398#default, just return the number
399    return $enumval;
400}
401
402push @EXPORT_OK, qw($L_BOGUS);
403push @{$EXPORT_TAGS{"logtype_t"}}, qw($L_BOGUS);
404
405$_logtype_t_VALUES{"L_BOGUS"} = $L_BOGUS;
406
407push @EXPORT_OK, qw($L_FATAL);
408push @{$EXPORT_TAGS{"logtype_t"}}, qw($L_FATAL);
409
410$_logtype_t_VALUES{"L_FATAL"} = $L_FATAL;
411
412push @EXPORT_OK, qw($L_ERROR);
413push @{$EXPORT_TAGS{"logtype_t"}}, qw($L_ERROR);
414
415$_logtype_t_VALUES{"L_ERROR"} = $L_ERROR;
416
417push @EXPORT_OK, qw($L_WARNING);
418push @{$EXPORT_TAGS{"logtype_t"}}, qw($L_WARNING);
419
420$_logtype_t_VALUES{"L_WARNING"} = $L_WARNING;
421
422push @EXPORT_OK, qw($L_INFO);
423push @{$EXPORT_TAGS{"logtype_t"}}, qw($L_INFO);
424
425$_logtype_t_VALUES{"L_INFO"} = $L_INFO;
426
427push @EXPORT_OK, qw($L_SUMMARY);
428push @{$EXPORT_TAGS{"logtype_t"}}, qw($L_SUMMARY);
429
430$_logtype_t_VALUES{"L_SUMMARY"} = $L_SUMMARY;
431
432push @EXPORT_OK, qw($L_START);
433push @{$EXPORT_TAGS{"logtype_t"}}, qw($L_START);
434
435$_logtype_t_VALUES{"L_START"} = $L_START;
436
437push @EXPORT_OK, qw($L_FINISH);
438push @{$EXPORT_TAGS{"logtype_t"}}, qw($L_FINISH);
439
440$_logtype_t_VALUES{"L_FINISH"} = $L_FINISH;
441
442push @EXPORT_OK, qw($L_DISK);
443push @{$EXPORT_TAGS{"logtype_t"}}, qw($L_DISK);
444
445$_logtype_t_VALUES{"L_DISK"} = $L_DISK;
446
447push @EXPORT_OK, qw($L_DONE);
448push @{$EXPORT_TAGS{"logtype_t"}}, qw($L_DONE);
449
450$_logtype_t_VALUES{"L_DONE"} = $L_DONE;
451
452push @EXPORT_OK, qw($L_PART);
453push @{$EXPORT_TAGS{"logtype_t"}}, qw($L_PART);
454
455$_logtype_t_VALUES{"L_PART"} = $L_PART;
456
457push @EXPORT_OK, qw($L_PARTPARTIAL);
458push @{$EXPORT_TAGS{"logtype_t"}}, qw($L_PARTPARTIAL);
459
460$_logtype_t_VALUES{"L_PARTPARTIAL"} = $L_PARTPARTIAL;
461
462push @EXPORT_OK, qw($L_SUCCESS);
463push @{$EXPORT_TAGS{"logtype_t"}}, qw($L_SUCCESS);
464
465$_logtype_t_VALUES{"L_SUCCESS"} = $L_SUCCESS;
466
467push @EXPORT_OK, qw($L_PARTIAL);
468push @{$EXPORT_TAGS{"logtype_t"}}, qw($L_PARTIAL);
469
470$_logtype_t_VALUES{"L_PARTIAL"} = $L_PARTIAL;
471
472push @EXPORT_OK, qw($L_FAIL);
473push @{$EXPORT_TAGS{"logtype_t"}}, qw($L_FAIL);
474
475$_logtype_t_VALUES{"L_FAIL"} = $L_FAIL;
476
477push @EXPORT_OK, qw($L_STRANGE);
478push @{$EXPORT_TAGS{"logtype_t"}}, qw($L_STRANGE);
479
480$_logtype_t_VALUES{"L_STRANGE"} = $L_STRANGE;
481
482push @EXPORT_OK, qw($L_CHUNK);
483push @{$EXPORT_TAGS{"logtype_t"}}, qw($L_CHUNK);
484
485$_logtype_t_VALUES{"L_CHUNK"} = $L_CHUNK;
486
487push @EXPORT_OK, qw($L_CHUNKSUCCESS);
488push @{$EXPORT_TAGS{"logtype_t"}}, qw($L_CHUNKSUCCESS);
489
490$_logtype_t_VALUES{"L_CHUNKSUCCESS"} = $L_CHUNKSUCCESS;
491
492push @EXPORT_OK, qw($L_STATS);
493push @{$EXPORT_TAGS{"logtype_t"}}, qw($L_STATS);
494
495$_logtype_t_VALUES{"L_STATS"} = $L_STATS;
496
497push @EXPORT_OK, qw($L_MARKER);
498push @{$EXPORT_TAGS{"logtype_t"}}, qw($L_MARKER);
499
500$_logtype_t_VALUES{"L_MARKER"} = $L_MARKER;
501
502push @EXPORT_OK, qw($L_CONT);
503push @{$EXPORT_TAGS{"logtype_t"}}, qw($L_CONT);
504
505$_logtype_t_VALUES{"L_CONT"} = $L_CONT;
506
507#copy symbols in logtype_t to constants
508push @{$EXPORT_TAGS{"constants"}},  @{$EXPORT_TAGS{"logtype_t"}};
509
510push @EXPORT_OK, qw(program_t_to_string);
511push @{$EXPORT_TAGS{"program_t"}}, qw(program_t_to_string);
512
513my %_program_t_VALUES;
514#Convert an enum value to a single string
515sub program_t_to_string {
516    my ($enumval) = @_;
517
518    for my $k (keys %_program_t_VALUES) {
519	my $v = $_program_t_VALUES{$k};
520
521	#is this a matching flag?
522	if ($enumval == $v) {
523	    return $k;
524	}
525    }
526
527#default, just return the number
528    return $enumval;
529}
530
531push @EXPORT_OK, qw($P_UNKNOWN);
532push @{$EXPORT_TAGS{"program_t"}}, qw($P_UNKNOWN);
533
534$_program_t_VALUES{"P_UNKNOWN"} = $P_UNKNOWN;
535
536push @EXPORT_OK, qw($P_PLANNER);
537push @{$EXPORT_TAGS{"program_t"}}, qw($P_PLANNER);
538
539$_program_t_VALUES{"P_PLANNER"} = $P_PLANNER;
540
541push @EXPORT_OK, qw($P_DRIVER);
542push @{$EXPORT_TAGS{"program_t"}}, qw($P_DRIVER);
543
544$_program_t_VALUES{"P_DRIVER"} = $P_DRIVER;
545
546push @EXPORT_OK, qw($P_REPORTER);
547push @{$EXPORT_TAGS{"program_t"}}, qw($P_REPORTER);
548
549$_program_t_VALUES{"P_REPORTER"} = $P_REPORTER;
550
551push @EXPORT_OK, qw($P_DUMPER);
552push @{$EXPORT_TAGS{"program_t"}}, qw($P_DUMPER);
553
554$_program_t_VALUES{"P_DUMPER"} = $P_DUMPER;
555
556push @EXPORT_OK, qw($P_CHUNKER);
557push @{$EXPORT_TAGS{"program_t"}}, qw($P_CHUNKER);
558
559$_program_t_VALUES{"P_CHUNKER"} = $P_CHUNKER;
560
561push @EXPORT_OK, qw($P_TAPER);
562push @{$EXPORT_TAGS{"program_t"}}, qw($P_TAPER);
563
564$_program_t_VALUES{"P_TAPER"} = $P_TAPER;
565
566push @EXPORT_OK, qw($P_AMFLUSH);
567push @{$EXPORT_TAGS{"program_t"}}, qw($P_AMFLUSH);
568
569$_program_t_VALUES{"P_AMFLUSH"} = $P_AMFLUSH;
570
571push @EXPORT_OK, qw($P_AMDUMP);
572push @{$EXPORT_TAGS{"program_t"}}, qw($P_AMDUMP);
573
574$_program_t_VALUES{"P_AMDUMP"} = $P_AMDUMP;
575
576push @EXPORT_OK, qw($P_AMIDXTAPED);
577push @{$EXPORT_TAGS{"program_t"}}, qw($P_AMIDXTAPED);
578
579$_program_t_VALUES{"P_AMIDXTAPED"} = $P_AMIDXTAPED;
580
581push @EXPORT_OK, qw($P_AMFETCHDUMP);
582push @{$EXPORT_TAGS{"program_t"}}, qw($P_AMFETCHDUMP);
583
584$_program_t_VALUES{"P_AMFETCHDUMP"} = $P_AMFETCHDUMP;
585
586push @EXPORT_OK, qw($P_AMCHECKDUMP);
587push @{$EXPORT_TAGS{"program_t"}}, qw($P_AMCHECKDUMP);
588
589$_program_t_VALUES{"P_AMCHECKDUMP"} = $P_AMCHECKDUMP;
590
591push @EXPORT_OK, qw($P_AMVAULT);
592push @{$EXPORT_TAGS{"program_t"}}, qw($P_AMVAULT);
593
594$_program_t_VALUES{"P_AMVAULT"} = $P_AMVAULT;
595
596#copy symbols in program_t to constants
597push @{$EXPORT_TAGS{"constants"}},  @{$EXPORT_TAGS{"program_t"}};
598
599push @EXPORT_OK, qw(find_log search_logfile dumps_match log_rename);
600
601push @EXPORT_OK, qw($amanda_log_trace_log);
602
603push @EXPORT_OK, qw(find_all_logs find_latest_log
604    get_current_log_timestamp
605    make_stats);
606
607
608use Amanda::Config qw ( :init :getconf config_dir_relative );
609use Amanda::Debug;
610
611sub find_all_logs
612{
613    my $logdir = shift @_ || config_dir_relative(getconf($CNF_LOGDIR));
614
615    opendir my $logdh, $logdir or die("can't read $logdir");
616    my @logfiles = sort grep { m{^log\.\d+\.\d+$} } readdir $logdh;
617
618    return @logfiles;
619}
620
621sub find_latest_log
622{
623    my $logdir = shift @_;
624    my @logs = find_all_logs($logdir || ());
625    return $logs[-1];
626}
627
628sub get_current_log_timestamp
629{
630    my $logfile = config_dir_relative(getconf($CNF_LOGDIR)) . "/log";
631    if (! -f $logfile) {
632	Amanda::Debug::warning("no current logfile '$logfile'");
633	return undef;
634    }
635
636    my $logh = open_logfile("$logfile");
637    if (!$logh) {
638	Amanda::Debug::warning("could not open logfile '$logfile'");
639	return undef;
640    }
641    while (my ($type, $prog, $str) = get_logline($logh)) {
642	if ($type == $L_START) {
643	    my ($ts) = ($str =~ /date (\d+)/);
644	    return $ts if $ts;
645	}
646    }
647
648    # no timestamp, apparently
649    Amanda::Debug::warning("no current timestamp found in logfile");
650    return undef;
651}
652
653sub make_stats {
654    my ($size, $duration, $orig_kb) = @_;
655
656    $duration = 0.1 if $duration <= 0;  # prevent division by zero
657    my $kb = $size/1024;
658    my $kps = "$kb.0"/$duration; # Perlish cast from BigInt to float
659
660    if (defined $orig_kb) {
661	return sprintf("[sec %f bytes %s kps %f orig-kb %s]", $duration, $size, $kps, $orig_kb);
662    } else {
663	return sprintf("[sec %f bytes %s kps %f]", $duration, $size, $kps);
664    }
665}
666
6671;
668