r15928@rob-kinyons-computer (orig r9227): rkinyon | 2007-03-12 10:12:34 -0400
[dbsrgits/DBM-Deep.git] / utils / upgrade_db.pl
CommitLineData
fbd470e4 1#!perl
f72b2dfb 2
3use 5.6.0;
4
5use strict;
6use warnings FATAL => 'all';
7
8use FindBin;
9use File::Spec ();
10use lib File::Spec->catdir( $FindBin::Bin, 'lib' );
11
12# This is for the latest version.
13use lib File::Spec->catdir( $FindBin::Bin, '..', 'lib' );
14
15use Getopt::Long qw( GetOptions );
16use Pod::Usage;
17
18my %headerver_to_module = (
19 '0' => 'DBM::Deep::09830',
20 '2' => 'DBM::Deep',
21);
22
23my %is_dev = (
24 '1' => 1,
25);
26
27my %opts = (
28 man => 0,
29 help => 0,
30 version => '1.0000',
31 autobless => 0,
32);
33GetOptions( \%opts,
34 'input=s', 'output=s', 'version:s', 'autobless:i',
35 'help|?', 'man',
36) || pod2man(2);
37pod2usage(1) if $opts{help};
38pod2usage(-exitstatus => 0, -verbose => 2) if $opts{man};
39
40pod2usage(-msg => "Missing required parameters.", verbose => 1)
41 unless $opts{input} && $opts{output};
42
43if ( $opts{input} eq $opts{output} ) {
44 _exit( "Cannot use the same filename for both input and output." );
45}
46
47unless ( -f $opts{input} ) {
48 _exit( "'$opts{input}' is not a file." );
49}
50
51my %db;
52{
53 my $ver = _read_file_header( $opts{input} );
54 if ( $is_dev{ $ver } ) {
55 _exit( "'$opts{input}' is a dev release and not supported." );
56 }
57
58 my $mod = $headerver_to_module{ $ver };
59 eval "use $mod;";
60 $db{input} = $mod->new({
61 file => $opts{input},
62 locking => 1,
63 autobless => $opts{autobless},
64 });
65 $db{input}->lock;
66}
67
68{
69 my $ver = $opts{version};
70 if ( $ver =~ /^0\.9[1-8]/ ) {
71 $ver = 0;
72 }
73 elsif ( $ver =~ /^0\.99/) {
74 $ver = 1;
75 }
76 elsif ( $ver =~ /^1\.000?0?/) {
77 $ver = 2;
78 }
79 else {
80 _exit( "'$ver' is an unrecognized version." );
81 }
82
83 if ( $is_dev{ $ver } ) {
84 _exit( "-version '$opts{version}' is a dev release and not supported." );
85 }
86
87 # First thing is to destroy the file, in case it's an incompatible version.
88 unlink $opts{output};
89
90 my $mod = $headerver_to_module{ $ver };
91 eval "use $mod;";
92 $db{output} = $mod->new({
93 file => $opts{output},
94 locking => 1,
95 autobless => $opts{autobless},
96 });
97 $db{output}->lock;
98}
99
100# Do the actual conversion. This is the code that compress uses.
101$db{input}->_copy_node( $db{output} );
102undef $db{output};
103
104################################################################################
105
106sub _read_file_header {
107 my ($file) = @_;
108
109 open my $fh, '<', $file
110 or _exit( "Cannot open '$file' for reading: $!" );
111
112 my $buffer = _read_buffer( $fh, 9 );
113 _exit( "'$file' is not a DBM::Deep file." )
114 unless length $buffer == 9;
115
116 my ($file_sig, $header_sig, $header_ver) = unpack( 'A4 A N', $buffer );
117
118 # SIG_FILE == 'DPDB'
119 _exit( "'$file' is not a DBM::Deep file." )
120 unless $file_sig eq 'DPDB';
121
122 # SIG_HEADER == 'h' - this means that this is a pre-1.0 file
123 return 0 unless ($header_sig eq 'h');
124
125 return $header_ver;
126}
127
128sub _read_buffer {
129 my ($fh, $len) = @_;
130 my $buffer;
131 read( $fh, $buffer, $len );
132 return $buffer;
133}
134
135sub _exit {
136 my ($msg) = @_;
137 pod2usage( -verbose => 0, -msg => $msg );
138}
139
140__END__
141
142=head1 NAME
143
144upgrade_db.pl
145
146=head1 SYNOPSIS
147
148 upgrade_db.pl -input <oldfile> -output <newfile>
149
150=head1 DESCRIPTION
151
152This will attempt to upgrade DB files from one version of DBM::Deep to
153another. The version of the input file is detected from the file header. The
154version of the output file defaults to the version of the distro in this file,
155but can be set, if desired.
156
157=head1 OPTIONS
158
159=over 4
160
161=item B<-input> (required)
162
163This is the name of original DB file.
164
165=item B<-output> (required)
166
167This is the name of target output DB file.
168
169=item B<-version>
170
171Optionally, you can specify the version of L<DBM::Deep> for the output file.
172This can either be an upgrade or a downgrade. The minimum version supported is
1730.91.
174
175If the version is the same as the input file, this acts like a compressed copy
176of the database.
177
178=item B<-autobless>
179
180In pre-1.0000 versions, autoblessing was an optional setting. This defaults to
181false.
182
183=item B<-help>
184
185Prints a brief help message, then exits.
186
187=item B<-man>
188
189Prints a much longer message, then exits;
190
191=back
192
193=head1 CAVEATS
194
195The following are known issues with this converter.
196
197=over 4
198
199=item * Diskspace requirements
200
201This will require about twice the diskspace of the input file.
202
203=item * Feature support
204
205Not all versions support the same features. In particular, internal references
206were supported in 0.983 and support was removed in 1.000. There is no
207detection of this by upgrade_db.pl.
208
209=back
210
211=head1 MAINTAINER(S)
212
213Rob Kinyon, L<rkinyon@cpan.org>
214
215Originally written by Rob Kinyon, L<rkinyon@cpan.org>
216
217=head1 LICENSE
218
219Copyright (c) 2007 Rob Kinyon. All Rights Reserved.
220This is free software, you may use it and distribute it under the
221same terms as Perl itself.
222
223=cut