aboutsummaryrefslogtreecommitdiff
diff options
context:
space:
mode:
authorSergey Poznyakoff <gray@gnu.org>2018-12-14 10:24:31 +0200
committerSergey Poznyakoff <gray@gnu.org>2018-12-14 11:10:27 +0200
commit441dccad18df38dae1623b567f1910ec6ffcc161 (patch)
treecad182f9895b12b44f117ca049a130c62e4a1f83
parent820419c1cc238a86caf4e1955446700895201ac1 (diff)
downloadglacier-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.pm55
-rw-r--r--lib/App/Glacier/Config.pm18
-rw-r--r--lib/App/Glacier/DB.pm41
-rw-r--r--lib/App/Glacier/DB/GDBM.pm35
-rw-r--r--lib/App/Glacier/Directory.pm10
-rw-r--r--lib/App/Glacier/Directory/GDBM.pm12
-rw-r--r--lib/App/Glacier/Job.pm3
-rw-r--r--lib/App/Glacier/Roster.pm4
-rw-r--r--lib/App/Glacier/Roster/GDBM.pm12
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;
11use App::Glacier::Config; 11use App::Glacier::Config;
12use Net::Amazon::Glacier; 12use Net::Amazon::Glacier;
13use App::Glacier::HttpCatch; 13use App::Glacier::HttpCatch;
14use App::Glacier::DB;
15use App::Glacier::Timestamp; 14use App::Glacier::Timestamp;
16use App::Glacier::Directory; 15use App::Glacier::Directory;
16use App::Glacier::Roster;
17 17
18use Digest::SHA qw(sha256_hex); 18use Digest::SHA qw(sha256_hex);
19use File::Path qw(make_path); 19use 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 {
185sub jobdb { 190sub 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
214sub _filename {
215 my ($self, $name) = @_;
216 $name =~ s/([^A-Za-z_0-9\.-])/sprintf("%%%02X", ord($1))/gex;
217 return $name;
218}
219
220sub directory { 216sub 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
1096sub lint { 1098sub 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
32sub 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
32sub new { 42sub new {