diff options
author | Sergey Poznyakoff <gray@gnu.org> | 2018-12-14 10:24:31 +0200 |
---|---|---|
committer | Sergey Poznyakoff <gray@gnu.org> | 2018-12-14 11:10:27 +0200 |
commit | 441dccad18df38dae1623b567f1910ec6ffcc161 (patch) | |
tree | cad182f9895b12b44f117ca049a130c62e4a1f83 | |
parent | 820419c1cc238a86caf4e1955446700895201ac1 (diff) | |
download | glacier-441dccad18df38dae1623b567f1910ec6ffcc161.tar.gz glacier-441dccad18df38dae1623b567f1910ec6ffcc161.tar.bz2 |
Rework the DB class system in order to facilitate backend implementation.
* lib/App/Glacier/Command.pm: Use configtest methods for
database configuration.
* lib/App/Glacier/Config.pm (as_hash): ignore special keys
(_lint): Increase error count if unknown keyword is encountered.
(lint): Optional arguments specify path to the statement from which
to start linting.
* lib/App/Glacier/DB.pm: Provide the configtest method.
* lib/App/Glacier/DB/GDBM.pm (new): Use the optional 'create'
keyword for testing whether to create the directory.
Implement the configtest method.
* lib/App/Glacier/Directory/GDBM.pm: Provide defaults for configtest.
* lib/App/Glacier/Directory.pm (new): Expand $vault in the actual
parameter values to the vault name.
* lib/App/Glacier/Job.pm: Remove unused variables.
* lib/App/Glacier/Roster.pm: New file.
* lib/App/Glacier/Roster/GDBM.pm: New file.
-rw-r--r-- | lib/App/Glacier/Command.pm | 55 | ||||
-rw-r--r-- | lib/App/Glacier/Config.pm | 18 | ||||
-rw-r--r-- | lib/App/Glacier/DB.pm | 41 | ||||
-rw-r--r-- | lib/App/Glacier/DB/GDBM.pm | 35 | ||||
-rw-r--r-- | lib/App/Glacier/Directory.pm | 10 | ||||
-rw-r--r-- | lib/App/Glacier/Directory/GDBM.pm | 12 | ||||
-rw-r--r-- | lib/App/Glacier/Job.pm | 3 | ||||
-rw-r--r-- | lib/App/Glacier/Roster.pm | 4 | ||||
-rw-r--r-- | lib/App/Glacier/Roster/GDBM.pm | 12 |
9 files changed, 133 insertions, 57 deletions
diff --git a/lib/App/Glacier/Command.pm b/lib/App/Glacier/Command.pm index 0888b4b..47bfce6 100644 --- a/lib/App/Glacier/Command.pm +++ b/lib/App/Glacier/Command.pm | |||
@@ -11,9 +11,9 @@ use App::Glacier::EclatCreds; | |||
11 | use App::Glacier::Config; | 11 | use App::Glacier::Config; |
12 | use Net::Amazon::Glacier; | 12 | use Net::Amazon::Glacier; |
13 | use App::Glacier::HttpCatch; | 13 | use App::Glacier::HttpCatch; |
14 | use App::Glacier::DB; | ||
15 | use App::Glacier::Timestamp; | 14 | use App::Glacier::Timestamp; |
16 | use App::Glacier::Directory; | 15 | use App::Glacier::Directory; |
16 | use App::Glacier::Roster; | ||
17 | 17 | ||
18 | use Digest::SHA qw(sha256_hex); | 18 | use Digest::SHA qw(sha256_hex); |
19 | use File::Path qw(make_path); | 19 | use File::Path qw(make_path); |
@@ -79,16 +79,14 @@ my %parameters = ( | |||
79 | section => { | 79 | section => { |
80 | job => { | 80 | job => { |
81 | section => { | 81 | section => { |
82 | file => { default => '/var/lib/glacier/job.db' }, | 82 | backend => { default => 'GDBM' }, |
83 | mode => { default => 0644 }, | 83 | '*' => '*' |
84 | ttl => { default => 72000, check => \&ck_number }, | ||
85 | }, | 84 | }, |
86 | }, | 85 | }, |
87 | inv => { | 86 | inv => { |
88 | section => { | 87 | section => { |
89 | directory => { default => '/var/lib/glacier/inv' }, | 88 | backend => { default => 'GDBM' }, |
90 | mode => { default => 0644 }, | 89 | '*' => '*' |
91 | ttl => { default => 72000, check => \&ck_number }, | ||
92 | } | 90 | } |
93 | } | 91 | } |
94 | } | 92 | } |
@@ -121,6 +119,13 @@ sub new { | |||
121 | parameters => \%parameters); | 119 | parameters => \%parameters); |
122 | exit(EX_CONFIG) unless $self->{_config}->parse(); | 120 | exit(EX_CONFIG) unless $self->{_config}->parse(); |
123 | 121 | ||
122 | App::Glacier::Roster->configtest($self->cfget(qw(database job backend)), | ||
123 | $self->config, 'database', 'job') | ||
124 | or exit(EX_CONFIG); | ||
125 | App::Glacier::Directory->configtest($self->cfget(qw(database inv backend)), | ||
126 | $self->config, 'database', 'inv') | ||
127 | or exit(EX_CONFIG); | ||
128 | |||
124 | unless ($self->{_config}->isset(qw(glacier access)) | 129 | unless ($self->{_config}->isset(qw(glacier access)) |
125 | && $self->{_config}->isset(qw(glacier secret))) { | 130 | && $self->{_config}->isset(qw(glacier secret))) { |
126 | if ($self->{_config}->isset(qw(glacier credentials))) { | 131 | if ($self->{_config}->isset(qw(glacier credentials))) { |
@@ -185,14 +190,11 @@ sub touchdir { | |||
185 | sub jobdb { | 190 | sub jobdb { |
186 | my $self = shift; | 191 | my $self = shift; |
187 | unless ($self->{_jobdb}) { | 192 | unless ($self->{_jobdb}) { |
188 | my $file = $self->cfget(qw(database job file)); | 193 | my $be = $self->cfget(qw(database job backend)); |
189 | $self->touchdir(dirname($file)); | 194 | $self->{_jobdb} = new App::Glacier::Roster( |
190 | $self->{_jobdb} = new App::Glacier::DB( | 195 | $be, |
191 | 'GDBM', | 196 | %{$self->config->as_hash(qw(database job)) // {}} |
192 | filename => $file, | 197 | ); |
193 | encoding => 'json', | ||
194 | mode => $self->cfget(qw(database job mode)) | ||
195 | ); | ||
196 | } | 198 | } |
197 | return $self->{_jobdb}; | 199 | return $self->{_jobdb}; |
198 | } | 200 | } |
@@ -211,29 +213,16 @@ sub describe_vault { | |||
211 | return timestamp_deserialize($res); | 213 | return timestamp_deserialize($res); |
212 | } | 214 | } |
213 | 215 | ||
214 | sub _filename { | ||
215 | my ($self, $name) = @_; | ||
216 | $name =~ s/([^A-Za-z_0-9\.-])/sprintf("%%%02X", ord($1))/gex; | ||
217 | return $name; | ||
218 | } | ||
219 | |||
220 | sub directory { | 216 | sub directory { |
221 | my ($self, $vault_name) = @_; | 217 | my ($self, $vault_name) = @_; |
222 | unless (exists($self->{_dir}{$vault_name})) { | 218 | unless (exists($self->{_dir}{$vault_name})) { |
223 | my $file = $self->cfget(qw(database inv directory)) | 219 | my $be = $self->cfget(qw(database inv backend)); |
224 | . '/' . $self->_filename($vault_name) . '.db'; | ||
225 | unless (-e $file) { | ||
226 | return undef unless $self->describe_vault($vault_name); | ||
227 | } | ||
228 | $self->touchdir($self->cfget(qw(database inv directory))); | ||
229 | $self->{_dir}{$vault_name} = | 220 | $self->{_dir}{$vault_name} = |
230 | new App::Glacier::Directory( | 221 | new App::Glacier::Directory( |
231 | 'GDBM', | 222 | $be, |
232 | filename => $file, | 223 | $vault_name, |
233 | encoding => 'json', | 224 | create => sub { $self->describe_vault($vault_name) }, |
234 | mode => $self->cfget(qw(database inv mode)), | 225 | %{$self->config->as_hash(qw(database inv)) // {}}); |
235 | ttl => $self->cfget(qw(database inv ttl)) | ||
236 | ); | ||
237 | } | 226 | } |
238 | return $self->{_dir}{$vault_name}; | 227 | return $self->{_dir}{$vault_name}; |
239 | } | 228 | } |
diff --git a/lib/App/Glacier/Config.pm b/lib/App/Glacier/Config.pm index f5232d6..33d54d2 100644 --- a/lib/App/Glacier/Config.pm +++ b/lib/App/Glacier/Config.pm | |||
@@ -272,7 +272,7 @@ sub error { | |||
272 | my $self = shift; | 272 | my $self = shift; |
273 | my $err = shift; | 273 | my $err = shift; |
274 | local %_ = @_; | 274 | local %_ = @_; |
275 | $err = "$_{locus}: $err" if exists $_{locus}; | 275 | $err = "$_{locus}: $err" if $_{locus}; |
276 | print STDERR "$err\n"; | 276 | print STDERR "$err\n"; |
277 | } | 277 | } |
278 | 278 | ||
@@ -378,7 +378,7 @@ sub check_mandatory { | |||
378 | while (my ($k, $d) = each %{$kw}) { | 378 | while (my ($k, $d) = each %{$kw}) { |
379 | if (ref($d) eq 'HASH') { | 379 | if (ref($d) eq 'HASH') { |
380 | if ($d->{mandatory} && !exists($section->{$k})) { | 380 | if ($d->{mandatory} && !exists($section->{$k})) { |
381 | $loc = $section->{-locus} if exists($section->{-locus}); | 381 | $loc = $section->{-locus} if $section->{-locus}; |
382 | $self->error(exists($d->{section}) | 382 | $self->error(exists($d->{section}) |
383 | ? "mandatory section [" | 383 | ? "mandatory section [" |
384 | . join(' ', @_, $k) | 384 | . join(' ', @_, $k) |
@@ -742,12 +742,13 @@ sub as_hash { | |||
742 | my $ref = $self->getref(@_); | 742 | my $ref = $self->getref(@_); |
743 | my $hroot = {}; | 743 | my $hroot = {}; |
744 | my @ar; | 744 | my @ar; |
745 | 745 | ||
746 | push @ar, [ '', $ref, $hroot ]; | 746 | push @ar, [ '', $ref, $hroot ]; |
747 | while (my $elt = shift @ar) { | 747 | while (my $elt = shift @ar) { |
748 | if (is_section_ref($elt->[1])) { | 748 | if (is_section_ref($elt->[1])) { |
749 | my $hr = $elt->[2]{$elt->[0]} = {}; | 749 | my $hr = $elt->[2]{$elt->[0]} = {}; |
750 | while (my ($kw, $val) = each %{$elt->[1]}) { | 750 | while (my ($kw, $val) = each %{$elt->[1]}) { |
751 | next if $kw =~ /^-/; | ||
751 | push @ar, [ $kw, $val, $hr ]; | 752 | push @ar, [ $kw, $val, $hr ]; |
752 | } | 753 | } |
753 | } else { | 754 | } else { |
@@ -1077,6 +1078,7 @@ sub _lint { | |||
1077 | } else { | 1078 | } else { |
1078 | $self->error("keyword \"$var\" is unknown", | 1079 | $self->error("keyword \"$var\" is unknown", |
1079 | locus => $value->{-locus}); | 1080 | locus => $value->{-locus}); |
1081 | $self->{error_count}++; | ||
1080 | } | 1082 | } |
1081 | } | 1083 | } |
1082 | } | 1084 | } |
@@ -1094,13 +1096,13 @@ after calling B<parse>. | |||
1094 | =cut | 1096 | =cut |
1095 | 1097 | ||
1096 | sub lint { | 1098 | sub lint { |
1097 | my ($self, $synt) = @_; | 1099 | my ($self, $synt, @path) = @_; |
1098 | 1100 | my $subtree = $self->getref(@path); | |
1099 | # $synt->{'*'} = { section => { '*' => 1 }} ; | 1101 | # $synt->{'*'} = { section => { '*' => 1 }} ; |
1100 | $self->_lint($synt, $self->{conf}); | 1102 | $self->_lint($synt, $subtree); |
1101 | $self->check_mandatory($synt, $self->{conf}); | 1103 | $self->check_mandatory($synt, $subtree); |
1102 | return 0 if $self->{error_count}; | 1104 | return 0 if $self->{error_count}; |
1103 | $self->fixup($synt); | 1105 | $self->fixup($synt, @path); |
1104 | return $self->{error_count} == 0; | 1106 | return $self->{error_count} == 0; |
1105 | } | 1107 | } |
1106 | 1108 | ||
diff --git a/lib/App/Glacier/DB.pm b/lib/App/Glacier/DB.pm index 536ef81..aec3e04 100644 --- a/lib/App/Glacier/DB.pm +++ b/lib/App/Glacier/DB.pm | |||
@@ -29,6 +29,16 @@ my %transcode = ( | |||
29 | ] | 29 | ] |
30 | ); | 30 | ); |
31 | 31 | ||
32 | sub mod_call { | ||
33 | my ($class, $backend, $code) = @_; | ||
34 | my $modname = $class . '::' . $backend; | ||
35 | my $modpath = $modname; | ||
36 | $modpath =~ s{::}{/}g; | ||
37 | $modpath .= '.pm'; | ||
38 | require $modpath; | ||
39 | return &{$code}($modname); | ||
40 | }; | ||
41 | |||
32 | sub new { | 42 | sub new { |