2 * Copyright (c) 2008, 2009, 2010 Zmanda, Inc. All Rights Reserved.
4 * This program is free software; you can redistribute it and/or modify it
5 * under the terms of the GNU General Public License version 2 as published
6 * by the Free Software Foundation.
8 * This program is distributed in the hope that it will be useful, but
9 * WITHOUT ANY WARRANTY; without even the implied warranty of MERCHANTABILITY
10 * or FITNESS FOR A PARTICULAR PURPOSE. See the GNU General Public License
13 * You should have received a copy of the GNU General Public License along
14 * with this program; if not, write to the Free Software Foundation, Inc.,
15 * 59 Temple Place, Suite 330, Boston, MA 02111-1307 USA
17 * Contact information: Zmanda Inc., 465 S. Mathilda Ave., Suite 300
18 * Sunnyvale, CA 94085, USA, or: http://www.zmanda.com
21 %module "Amanda::Tapelist"
22 %include "amglue/amglue.swg"
23 %include "exception.i"
25 %include "Amanda/Tapelist.pod"
32 use Amanda::Debug qw(:logging);
33 use Amanda::Config qw( config_dir_relative );
35 use Fcntl qw(:flock); # import LOCK_* constants
41 my ($filename, $lock ) = @_;
43 filename => $filename,
44 lockname => $filename . '.lock',
77 C_read_tapelist($self->{'filename'});
79 $self->_read_tapelist();
82 sub lookup_tapelabel {
86 for my $tle (@{$self->{'tles'}}) {
87 return $tle if ($tle->{'label'} eq $label);
97 $self->_update_positions();
98 return $self->{'tles'}->[$position-1];
101 sub lookup_tapedate {
103 my ($datestamp) = @_;
105 for my $tle (@{$self->{'tles'}}) {
106 return $tle if ($tle->{'datestamp'} eq $datestamp);
112 sub remove_tapelabel {
116 for (my $i = 0; $i < @{$self->{tles}}; $i++) {
117 if ($self->{tles}->[$i]->{'label'} eq $label) {
118 splice @{$self->{tles}}, $i, 1;
119 $self->_update_positions();
127 my ($datestamp, $label, $comment, $reuse) = @_;
128 $reuse = 1 if !defined $reuse;
130 # prepend this (presumably new) volume to the beginning of the list
131 unshift @{$self->{'tles'}}, {
132 'datestamp' => $datestamp,
135 'comment' => $comment,
137 $self->_update_positions();
144 $filename = $self->{'filename'} if !defined $filename;
146 my $new_tapelist_file = $filename . "-new-" . time();
148 open(my $fhn, ">", $new_tapelist_file) or die("Could not open '$new_tapelist_file' for writing: $!");
149 for my $tle (@{$self->{tles}}) {
150 my $datestamp = $tle->{'datestamp'};
151 my $label = $tle->{'label'};
152 my $reuse = $tle->{'reuse'} ? 'reuse' : 'no-reuse';
153 my $comment = (defined $tle->{'comment'})? (" #" . $tle->{'comment'}) : '';
154 $result &&= print $fhn "$datestamp $label $reuse$comment\n";
156 my $result_close = close($fhn);
157 $result &&= $result_close;
159 return if (!$result);
161 unless (move($new_tapelist_file, $filename)) {
162 die ("failed to rename '$new_tapelist_file' to '$filename': $!");
165 # re-read from the C side to synchronize
166 C_read_tapelist($filename);
176 return if !exists $self->{'fl'};
178 $self->{'fl'}->unlock();
187 if (!-e $self->{'lockname'}) {
188 open(my $fhl, ">>", $self->{'lockname'});
191 my $fl = Amanda::Util::file_lock->new($self->{'lockname'});
192 while(($r = $fl->lock()) == 1) {
204 open(my $fh, "<", $self->{'filename'}) or return $self;
205 while (my $line = <$fh>) {
206 my ($datestamp, $label, $reuse, $comment)
207 = $line =~ m/^([0-9]*)\s([^\s]*)\s(reuse|no-reuse)\s*(?:\#(.*))?$/mx;
208 next if !defined $datestamp; # silently filter out bogus lines
210 'datestamp' => $datestamp,
212 'reuse' => ($reuse eq 'reuse'),
213 'comment' => $comment,
218 # sort in descending order by datestamp, sorting on position, too, to ensure
219 # that entries with the same datestamp stay in the right order
220 $self->{'tles'} = \@tles;
221 $self->_update_positions();
223 $b->{'datestamp'} cmp $a->{'datestamp'}
224 || $a->{'position'} <=> $b->{'position'}
227 $self->{'tles'} = \@tles;
229 # and re-calculate the positions
230 $self->_update_positions(\@tles);
233 # update the 'position' key for each TLE
234 sub _update_positions {
236 my $tles = $self->{'tles'};
237 for (my $i = 0; $i < scalar @$tles; $i++) {
238 $tles->[$i]->{'position'} = $i+1;
244 char *get_last_reusable_tape_label(int skip);
245 char *list_new_tapes(int nb);
247 /* C functions -- should be called *only* from within this module */
249 %rename(C_read_tapelist) read_tapelist;
250 int read_tapelist(char *tapefile);
252 %rename(C_clear_tapelist) clear_tapelist;
253 void clear_tapelist(void);