Imported Upstream version 3.1.0
[debian/amanda] / perl / Amanda / Curinfo.pm
1 # Copyright (c) 2010 Zmanda, Inc.  All Rights Reserved.
2 #
3 # This program is free software; you can redistribute it and/or modify it
4 # under the terms of the GNU General Public License version 2 as published
5 # by the Free Software Foundation.
6 #
7 # This program is distributed in the hope that it will be useful, but
8 # WITHOUT ANY WARRANTY; without even the implied warranty of MERCHANTABILITY
9 # or FITNESS FOR A PARTICULAR PURPOSE.  See the GNU General Public License
10 # for more details.
11 #
12 # You should have received a copy of the GNU General Public License along
13 # with this program; if not, write to the Free Software Foundation, Inc.,
14 # 59 Temple Place, Suite 330, Boston, MA  02111-1307 USA
15 #
16 # Contact information: Zmanda Inc., 465 S. Mathilda Ave., Suite 300
17 # Sunnyvale, CA 94085, USA, or: http://www.zmanda.com
18
19 package Amanda::Curinfo;
20
21 use strict;
22 use warnings;
23 use Carp;
24 use File::Copy;
25 use File::Path qw( mkpath );
26
27 use Amanda::Debug qw( :logging );
28 use Amanda::Util qw( sanitise_filename );
29
30 use Amanda::Curinfo::Info;
31
32 =head1 NAME
33
34 Amanda::Curinfo - Perl extension for representing the curinfo database
35
36 =head1 SYNOPSIS
37
38    use Amanda::Curinfo;
39    use Amanda::Curinfo::Info;
40
41    ...
42
43    my $ci = Amanda::Curinfo->new($somedir);
44    my $info = $ci->get_info($host, $disk);
45
46    ...
47
48    $ci->put_info($host, $disk, $newinfo);
49
50    ...
51
52    $ci->del_info($oldhost, $olddisk);
53
54 =head1 DESCRIPTION
55
56 C<Amanda::Curinfo> is a pure perl implementation of the older infofile
57 libraries.
58
59 This package manages a directory of files, referred to in the code as
60 an C<$infodir>, that contain dump data.  Each of these files is stored
61 in a nested directory structure by its host and disk name.  These
62 files can be accessed and modified using the provided functions with
63 the help of the L<Amanda::Curinfo::Info> class.
64
65 Note that this terminology is slightly different from the older
66 infofile.h implementation.  Users with no experience with infofile.h
67 can skip to the interface section.
68
69 In the API for infofile.h, the term C<infofile> actually refers a
70 directory.  This directory is called an C<infodir> within the
71 infofile.c code.  This directory held text files, which are referred
72 to as both C<infofile> and C<txinfofile> internally to infofile.c.
73
74 This rewrite simplifies the terminology by referring to the storage
75 directory as an C<$infodir> and an individual data-storing file as a
76 C<$infofile>.
77
78 =head1 INTERFACE
79
80
81 C<Amanda::Curinfo> is an interface to retrieve and store info files
82 regarding the backup history of DLEs.
83
84 C<Amanda::Curinfo> provides three major routines for handling info
85 file data.
86
87 The C<Amanda::Curinfo> constructor is pretty straightforward:
88
89    my $ci = Amanda::Curinfo->new($infodir);
90
91 Where C<$infodir> is a directory.  In order to retrieve a previously
92 stored info file if the host and disk are known, one can use
93
94    my $info = $ci->get_info($host, $disk);
95
96 Once the structure has been updated, it may be re-written to the
97 database in a similar fashion:
98
99   $ci->put_info($host, $disk, $info);
100
101 If one would like to erase an existing info entry in an infodir, the
102 usage is the same as retrieving an info object.
103
104   $ci->del_info($host, $disk);
105
106 To create a new info object, please see the documentation for
107 L<Amanda::Curinfo::Info>.
108
109 =head1 SEE ALSO
110
111 This module is meant to replicate the behavior of the library
112 described in server-src/infofile.h.  If anyone notices any major
113 problems, please report them.
114
115 =head1 AUTHOR
116
117 Paul C. Mantz E<lt>pcmantz@zmanda.comE<gt>
118
119 =cut
120
121
122 sub new
123 {
124     my ($class, $infodir) = @_;
125
126     (defined $infodir)
127       || croak("error: infodir not provided to Amanda::Curinfo");
128
129     my $self = { infodir => $infodir };
130
131     bless $self, $class;
132     return $self;
133 }
134
135 sub get_info
136 {
137     my ($self, $host, $disk) = @_;
138
139     my $infodir  = $self->{infodir};
140     my $host_q   = sanitise_filename($host);
141     my $disk_q   = sanitise_filename($disk);
142     my $infofile = "$infodir/$host_q/$disk_q/info";
143
144     return Amanda::Curinfo::Info->new($infofile);
145 }
146
147 sub put_info
148 {
149     my ($self, $host, $disk, $info) = @_;
150
151     my $infodir     = $self->{infodir};
152     my $host_q      = sanitise_filename($host);
153     my $disk_q      = sanitise_filename($disk);
154     my $infofiledir = "$infodir/$host_q/$disk_q";
155     my $infofile    = "$infofiledir/info";
156     my $infofile_tmp = "$infofile.tmp";
157
158     if (-e $infofile) {
159         copy($infofile, $infofile_tmp)
160           || croak "error: couldn't back up $infofile";
161     } elsif (!-d $infofiledir) {
162         mkpath($infofiledir)
163           || croak "error: couldn't make path $infofiledir";
164     }
165
166     my $restore = sub {
167         if (-e $infofile_tmp) {
168             copy($infofile_tmp, $infofile)
169               || croak
170               "error: couldn't restore infofile from backup $infofile_tmp";
171             unlink $infofile_tmp;
172         }
173         croak "error encountered when writing info to $infofile";
174     };
175
176     $info->write_to_file($infofile) || $restore->();
177     unlink $infofile_tmp if -e $infofile_tmp;
178     return 1;
179 }
180
181 sub del_info
182 {
183     my ($self, $host, $disk) = @_;
184
185     my $infodir  = $self->{infodir};
186     my $host_q   = sanitise_filename($host);
187     my $disk_q   = sanitise_filename($disk);
188     my $infofile = "$infodir/$host_q/$disk_q/info";
189
190     return unlink $infofile;
191 }
192
193 1;