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