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