File Coverage

blib/lib/App/MonM/Store.pm
Criterion Covered Total %
statement 133 173 76.8
branch 22 60 36.6
condition 10 41 24.3
subroutine 26 29 89.6
pod 10 10 100.0
total 201 313 64.2


line stmt bran cond sub pod time code
1             package App::MonM::Store; # $Id: Store.pm 76 2019-07-07 05:20:28Z abalama $
2 2     2   53402 use strict;
  2         10  
  2         48  
3 2     2   466 use utf8;
  2         14  
  2         7  
4              
5             =encoding utf8
6              
7             =head1 NAME
8              
9             App::MonM::Store - DBI interface for checkit's data storing
10              
11             =head1 VERSION
12              
13             Version 1.00
14              
15             =head1 SYNOPSIS
16              
17             use App::MonM::Store;
18              
19             my $dbi = new App::MonM::Store(
20             dsn => "DBI:mysql:database=monm;host=mysql.example.com",
21             user => "username",
22             password => "password",
23             set => [
24             "RaiseError 0",
25             "PrintError 0",
26             "mysql_enable_utf8 1",
27             ],
28             );
29             print STDERR $dbi->error if $dbi->error;
30              
31             =head1 DESCRIPTION
32              
33             DBI interface for checkit's data storing
34              
35             =head2 new
36              
37             my $dbi = new App::MonM::Store(
38             dsn => "DBI:mysql:database=monm;host=mysql.example.com",
39             user => "username",
40             password => "password",
41             set => [
42             "RaiseError 0",
43             "PrintError 0",
44             "mysql_enable_utf8 1",
45             ],
46             );
47              
48             Creates DBI object
49              
50             =head2 add
51              
52             $dbi->add(
53             name => "foo",
54             type => "http",
55             source => "http://example.com",
56             status => 1,
57             message => "Ok"
58             ) or die $dbi->error;
59              
60             Add new record on database
61              
62             =head2 clean
63              
64             $dbi->clean(
65             period => 600
66             ) or die $dbi->error;
67              
68             Delete too old records from database
69              
70             =head2 del
71              
72             $dbi->del(
73             id => 1
74             ) or die $dbi->error;
75              
76             Delete record from database
77              
78             =head2 dsn
79              
80             my $dsn = $dbi->dsn;
81              
82             Returns DSN string of current database connection
83              
84             =head2 error
85              
86             my $error = $dbi->error;
87             $dbi->error("Error message");
88              
89             Gets/sets error string
90              
91             =head2 get
92              
93             my %info = $dbi->get(
94             name => "foo"
95             );
96              
97             Gets information about file from database
98              
99             Format:
100              
101             {
102             id => 1,
103             time => 123456789,
104             name => "foo"
105             type => "http",
106             source => "http://example.com"
107             status => 1,
108             message => "Ok"
109             }
110              
111             =over 4
112              
113             =item B
114              
115             The Record ID. Autoincremented value!
116              
117             =item B
118              
119             The checking message
120              
121             =item B
122              
123             Name of checkit section
124              
125             =item B
126              
127             Source Name: URL, DSN or command
128              
129             =item B
130              
131             Status of checking: 000-111 as binary notation
132              
133             Default: 0
134              
135             =item B
136              
137             Time of record insert
138              
139             Default: time()
140              
141             =item B
142              
143             Type of checkit source: http, dbi, command
144              
145             Default: http
146              
147             =back
148              
149             =head2 is_sqlite
150              
151             print $dbi->is_sqlite ? "Is SQLite" : "Is not SQLite"
152              
153             Returns true if type of current database is SQLite
154              
155             =head2 getall
156              
157             my @files = $dbi->getall();
158              
159             Returns list of all checkit values
160              
161             Record format of return result: see L
162              
163             =head2 set
164              
165             $dbi->set(
166             id => 1,
167             name => "foo",
168             type => "http",
169             source => "http://example.com",
170             status => 1,
171             message => "Ok"
172             ) or die $dbi->error;
173              
174             Update existing record on database
175              
176             =head1 SEE ALSO
177              
178             L, L
179              
180             =head1 AUTHOR
181              
182             Serż Minus (Sergey Lepenkov) L Eabalama@cpan.orgE
183              
184             =head1 COPYRIGHT
185              
186             Copyright (C) 1998-2019 D&D Corporation. All Rights Reserved
187              
188             =head1 LICENSE
189              
190             This program is free software; you can redistribute it and/or
191             modify it under the same terms as Perl itself.
192              
193             See C file and L
194              
195             =cut
196              
197 2     2   94 use vars qw/ $VERSION /;
  2         3  
  2         98  
198             $VERSION = '1.00';
199              
200 2     2   27 use Carp;
  2         5  
  2         85  
201 2     2   714 use CTK::DBI;
  2         174873  
  2         66  
202 2     2   15 use CTK::Util qw/ touch /;
  2         4  
  2         75  
203 2     2   378 use CTK::ConfGenUtil;
  2         822  
  2         161  
204 2     2   352 use CTK::TFVals qw/ :ALL /;
  2         1678  
  2         335  
205 2     2   14 use File::Spec;
  2         3  
  2         42  
206              
207 2     2   346 use App::MonM::Const;
  2         5  
  2         101  
208 2     2   320 use App::MonM::Util qw/ set2attr /;
  2         4  
  2         113  
209              
210             use constant {
211 2         149 DB_FILENAME => 'monm.db',
212             DEFAULT_DSN_MASK => 'dbi:SQLite:dbname=%s',
213             DEFAULT_DBI_ATTR => {
214             dsn => '', # See DEFAULT_DSN_MASK
215             user => '',
216             password => '',
217             set => [
218             'RaiseError 0',
219             'PrintError 0',
220             'sqlite_unicode 1',
221             ],
222             },
223 2     2   11 };
  2         3  
224              
225 2     2   10 use constant CHECKIT_DDL => <<'DDL';
  2         4  
  2         109  
226             CREATE TABLE IF NOT EXISTS monm (
227             `id` INTEGER PRIMARY KEY AUTOINCREMENT NOT NULL,
228             `time` NUMERIC DEFAULT 0, -- time()
229             `name` CHAR(255) DEFAULT NULL, -- name of checkit section
230             `type` CHAR(32) DEFAULT NULL, -- http/dbi/command
231             `source` CHAR(255) DEFAULT NULL, -- URL/DSN/Command
232             `status` INTEGER DEFAULT 0, -- status value
233             `message` TEXT DEFAULT NULL -- message
234             )
235             DDL
236              
237 2     2   11 use constant CHECKIT_INSERT => <<'DML';
  2         3  
  2         92  
238             INSERT INTO monm
239             (`time`, `name`, `type`, `source`, `status`, `message`)
240             VALUES
241             (?, ?, ?, ?, ?, ?)
242             DML
243              
244 2     2   10 use constant CHECKIT_UPDATE => <<'DML';
  2         3  
  2         87  
245             UPDATE monm SET
246             `time` = ?, `name` = ?, `type` = ?, `source` = ?, `status` = ?, `message` = ?
247             WHERE `id` = ?
248             DML
249              
250 2     2   10 use constant CHECKIT_DELETE => <<'DML';
  2         3  
  2         79  
251             DELETE FROM monm WHERE `id` = ?
252             DML
253              
254 2     2   9 use constant CHECKIT_CLEAN => <<'DML';
  2         2  
  2         86  
255             DELETE FROM monm WHERE `time` < ?
256             DML
257              
258 2     2   10 use constant CHECKIT_SELECT => <<'DML';
  2         4  
  2         80  
259             SELECT `id`, `time`, `name`, `type`, `source`, `status`, `message`
260             FROM monm
261             WHERE `name` = ?
262             DML
263              
264 2     2   8 use constant CHECKIT_SELECT_ALL => <<'DML';
  2         4  
  2         2427  
265             SELECT `id`, `time`, `name`, `type`, `source`, `status`, `message`
266             FROM monm
267             DML
268              
269             sub new {
270 1     1 1 81 my $class = shift;
271 1         3 my %args = @_;
272 1 50       4 unless ($args{dsn}) {
273 1         2 my $dda = DEFAULT_DBI_ATTR;
274 1         5 foreach (%$dda) {
275 8   66     26 $args{$_} //= $dda->{$_}
276             }
277             }
278 1   50     6 my $file = $args{file} || DB_FILENAME;
279 1   33     7 my $dsn = $args{dsn} || sprintf(DEFAULT_DSN_MASK, $file);
280              
281             # DB
282             my $db = new CTK::DBI(
283             -dsn => $dsn,
284             -debug => 0,
285             -username => $args{'user'},
286             -password => $args{'password'},
287             -attr => set2attr($args{'set'}),
288             $args{timeout} ? (
289             -timeout_connect => $args{timeout},
290             -timeout_request => $args{timeout},
291 1 50       6 ) : (),
292             );
293 1 50       9975 my $dbh = $db->connect if $db;
294              
295             # SQLite
296 1         8 my $fnew = 0;
297 1         2 my $issqlite = 0;
298 1 50 33     9 if ($dbh && $dsn =~ /SQLite/i) {
299 1         8 $file = $dbh->sqlite_db_filename();
300 1 50 33     26 unless ($file && (-e $file) && !(-z $file)) {
      33        
301 1         7 touch($file);
302 1         91 chmod(0666, $file);
303 1         4 $fnew = 1;
304             }
305 1         2 $issqlite = 1;
306             }
307              
308 1         3 my $error = "";
309 1 50       6 if (!$db) {
    50          
    50          
310 0         0 $error = sprintf("Can't init database \"%s\"", $dsn);
311             } elsif (!$dbh) {
312 0   0     0 $error = sprintf("Can't connect to database \"%s\": %s", $dsn, $DBI::errstr || "unknown error");
313             } elsif ($fnew) {
314 1         5 $db->execute(CHECKIT_DDL);
315 1         12254 $error = $dbh->errstr();
316             }
317 1 50       5 unless ($error) {
318 1 50 0     7 $error = sprintf("Can't init database \"%s\". Ping failed: %s",
319             $dsn, $dbh->errstr() || "unknown error") unless $dbh->ping;
320             }
321              
322 1         43 my $self = bless {
323             file => $file,
324             issqlite=> $issqlite,
325             dsn => $dsn,
326             error => $error,
327             db => $db,
328             }, $class;
329              
330 1         6 return $self;
331             }
332             sub error {
333 10     10 1 45 my $self = shift;
334 10         15 my $err = shift;
335 10 100       36 return $self->{error} unless defined $err;
336 6         28 $self->{error} = $err;
337 6         10 return $self->{error};
338             }
339             sub dsn {
340 0     0 1 0 my $self = shift;
341 0         0 return $self->{dsn};
342             }
343             sub is_sqlite {
344 0     0 1 0 my $self = shift;
345 0 0       0 return $self->{issqlite} ? 1 : 0;
346             }
347             sub add {
348 1     1 1 2 my $self = shift;
349 1         7 my %params = @_;
350 1         3 my $db = $self->{db};
351 1 50       4 unless ($db) {
352 0 0       0 $self->error(sprintf("Database \"%s\" connect failed", $self->dsn))
353             unless $self->error;
354 0         0 return 0;
355             }
356 1         3 $self->error("");
357             $db->execute(CHECKIT_INSERT,
358             time(),
359             $params{name},
360             $params{type},
361             $params{source},
362             $params{status} || 0,
363             $params{message},
364 1   50     10 )->finish;
365 1 50       9201 if (my $dberr = $db->connect->errstr()) {
366 0   0     0 $self->error($dberr || $DBI::errstr || "unknown error");
367 0         0 return 0;
368             }
369 1         13 return 1;
370             }
371             sub set {
372 1     1 1 2 my $self = shift;
373 1         6 my %params = @_;
374 1         2 my $db = $self->{db};
375 1 50       3 unless ($db) {
376 0 0       0 $self->error(sprintf("Database \"%s\" connect failed", $self->dsn))
377             unless $self->error;
378 0         0 return 0;
379             }
380 1         4 $self->error("");
381             $db->execute(CHECKIT_UPDATE,
382             time(),
383             $params{name},
384             $params{type},
385             $params{source},
386             $params{status} || 0,
387             $params{message},
388             $params{id},
389 1   50     6 )->finish;
390 1 50       8248 if (my $dberr = $db->connect->errstr()) {
391 0   0     0 $self->error($dberr || $DBI::errstr || "unknown error");
392 0         0 return 0;
393             }
394 1         13 return 1;
395             }
396             sub del {
397 1     1 1 3 my $self = shift;
398 1         3 my %params = @_;
399 1         2 my $db = $self->{db};
400 1 50       4 unless ($db) {
401 0 0       0 $self->error(sprintf("Database \"%s\" connect failed", $self->dsn))
402             unless $self->error;
403 0         0 return 0;
404             }
405 1         4 $self->error("");
406 1         4 $db->execute(CHECKIT_DELETE, $params{id})->finish;
407              
408 1 50       7034 if (my $dberr = $db->connect->errstr()) {
409 0   0     0 $self->error($dberr || $DBI::errstr || "unknown error");
410 0         0 return 0;
411             }
412 1         11 return 1;
413             }
414             sub get {
415 2     2 1 5 my $self = shift;
416 2         6 my %params = @_;
417 2         4 my $db = $self->{db};
418 2 50       5 unless ($db) {
419 0 0       0 $self->error(sprintf("Database \"%s\" connect failed", $self->dsn))
420             unless $self->error;
421 0         0 return;
422             }
423 2         6 $self->error("");
424 2   50     6 my $name = $params{name} || "";
425 2         6 my %info = $db->recordh(CHECKIT_SELECT, $name);
426              
427 2 50       777 if (my $dberr = $db->connect->errstr()) {
428 0   0     0 $self->error($dberr || $DBI::errstr || "unknown error");
429 0         0 return ();
430             }
431 2         30 return %info;
432             }
433             sub getall {
434 1     1 1 251 my $self = shift;
435 1         3 my %params = @_;
436 1         2 my $db = $self->{db};
437 1 50       4 unless ($db) {
438 0 0       0 $self->error(sprintf("Database \"%s\" connect failed", $self->dsn))
439             unless $self->error;
440 0         0 return ();
441             }
442 1         3 $self->error("");
443 1         5 my %table = $db->tableh("id", CHECKIT_SELECT_ALL);
444 1 50       425 if (my $dberr = $db->connect->errstr()) {
445 0   0     0 $self->error($dberr || $DBI::errstr || "unknown error");
446 0         0 return ();
447             }
448 1         10 my @out = ();
449 1         4 foreach my $k (sort {$a <=> $b} keys %table) {
  0         0  
450 1         3 push @out, $table{$k};
451             }
452 1         4 return @out;
453             }
454             sub clean {
455 0     0 1   my $self = shift;
456 0           my %params = @_;
457 0           my $db = $self->{db};
458 0 0         unless ($db) {
459 0 0         $self->error(sprintf("Database \"%s\" connect failed", $self->dsn))
460             unless $self->error;
461 0           return 0;
462             }
463 0           $self->error("");
464 0   0       my $period = $params{period} || 0;
465 0           $db->execute(CHECKIT_CLEAN, time() - $period)->finish;
466              
467 0 0         if (my $dberr = $db->connect->errstr()) {
468 0   0       $self->error($dberr || $DBI::errstr || "unknown error");
469 0           return 0;
470             }
471 0           return 1;
472             }
473              
474             1;
475              
476             __END__