File Coverage

blib/lib/Collection/Storable.pm
Criterion Covered Total %
statement 83 84 98.8
branch 7 10 70.0
condition 6 7 85.7
subroutine 17 17 100.0
pod 2 3 66.6
total 115 121 95.0


line stmt bran cond sub pod time code
1             package Collection::Storable;
2              
3             =head1 NAME
4              
5             Collection::Storable - class for collections of data, stored in files.
6              
7             =head1 SYNOPSIS
8              
9             use File::Temp qw/ tempfile tempdir /;
10             my $tmp_dir = tempdir();
11             my $coll = new Collection::Storable:: $tmp_dir
12              
13             =head1 DESCRIPTION
14              
15             Class for collections of data, stored in files.
16              
17             =head1 METHODS
18              
19             =head2 new
20              
21             Creates a new Collection::Storable object.
22              
23             my $coll = new Collection::Storable:: $tmp_dir
24              
25             =cut
26              
27 1     1   1480 use Collection;
  1         1  
  1         35  
28 1     1   5 use Collection::Utl::Base;
  1         2  
  1         37  
29 1     1   6 use Data::Dumper;
  1         1  
  1         39  
30 1     1   6 use Collection::Utl::ActiveRecord;
  1         1  
  1         70  
31 1     1   998 use Storable qw(lock_nstore lock_retrieve);
  1         3587  
  1         74  
32              
33 1     1   8 use strict;
  1         2  
  1         31  
34 1     1   5 use warnings;
  1         3  
  1         816  
35              
36             our @ISA = qw(Collection);
37             our $VERSION = '0.01';
38              
39             attributes qw/ _store_path /;
40              
41             sub _init {
42 2     2   3 my $self = shift;
43 2   100     27 my $path = shift || return undef;
44 1 50       7 $path .= "/" unless $path =~ m%/$%;
45 1         38 $self->_store_path($path);
46 1         9 $self->SUPER::_init();
47 1         6 return 1;
48             }
49              
50             =head2 key2path [, , ...]
51              
52             translate keys to store path
53              
54             return hash of
55              
56             {
57             =>
58              
59             }
60              
61             =cut
62              
63             sub key2path {
64 11     11 1 14 my $self = shift;
65 11         23 my %res = ();
66 11         33 @res{@_} = @_;
67 11         34 return \%res;
68             }
69              
70             =head2 path2key [, , ...]
71              
72             translate store path to key
73              
74             return hash of
75              
76             {
77             =>
78              
79             }
80              
81             =cut
82              
83             sub path2key {
84 1     1 1 2 my $self = shift;
85 1         3 my %res = ();
86 1         4 @res{@_} = @_;
87 1         10 return \%res;
88             }
89              
90             sub _delete {
91 1     1   2 my $self = shift;
92 1         4 my @ids = @_;
93 1         28 my $path = $self->_store_path;
94              
95             #convert ids to pathes
96 1         4 my $key2path = $self->key2path(@ids);
97 1         145 unlink( $path . $_ ) for values %$key2path;
98 1         8 [ keys %$key2path ];
99             }
100              
101             sub _create {
102 2     2   3 my $self = shift;
103 2         16 my %to_save = @_;
104 2         8 $self->_store( \%to_save );
105 2         4508 return \%to_save;
106             }
107              
108             sub _fetch {
109 5     5   10 my $self = shift;
110 5         10 my @ids = @_;
111 5         139 my $path = $self->_store_path;
112              
113             #convert keys to path
114 5         15 my $key2path = $self->key2path(@ids);
115 5         39 my %res = ();
116 5         24 while ( my ( $key, $kpath ) = each %$key2path ) {
117 6         85 my $fpath = $path . $kpath;
118 6 100       132 next unless -e $fpath;
119 4         15 $res{$key} = lock_retrieve($fpath);
120             }
121 5         297 \%res;
122             }
123              
124             sub _prepare_record {
125 4     4   6 my ( $self, $key, $ref ) = @_;
126 4         5 my %hash;
127 4         24 tie %hash, 'Collection::Utl::ActiveRecord', hash => $ref;
128 4         13 return \%hash;
129             }
130              
131             sub _store {
132 3     3   7 my $self = shift;
133 3         4 my $in = shift;
134 3         84 my $path = $self->_store_path;
135 3         16 while ( my ( $key, $val ) = each %$in ) {
136 4         192 my $file_name = $path . $self->key2path($key)->{$key};
137 4   50     27 lock_nstore( {%$val} || {}, $file_name );
138             }
139             }
140              
141             sub __get_list_files {
142 1     1   2 my $self = shift;
143 1         2 my $path = shift;
144 1         3 my @res = ();
145 1 50       46 if ( opendir DIR, $path ) {
146 1         37 while ( my $name = readdir DIR ) {
147 4 100 100     26 next if ( $name eq '.' ) or ( $name eq '..' );
148 2         5 my $fpath = $path . $name;
149 2 50       37 if ( -d $fpath ) {
150 0         0 push @res, $self->__get_list_files($fpath);
151             }
152             else {
153 2         8 push @res, $fpath;
154             }
155             }
156 1         15 closedir DIR;
157             }
158             return @res
159              
160 1         4 }
161              
162             sub list_ids {
163 1     1 0 2 my $self = shift;
164 1         30 my $path = $self->_store_path;
165              
166             #get content of path
167 1         4 my @paths = $self->__get_list_files($path);
168 1         3 my $prefix_len = length $path;
169              
170             #cut root path
171 1         6 $_ = substr( $_, $prefix_len, length($_) - $prefix_len ) for @paths;
172 1         2 return [ values %{ $self->path2key(@paths) } ];
  1         4  
173             }
174              
175             1;
176             __END__