File Coverage

blib/lib/Catmandu/Store/File/Multi/Bag.pm
Criterion Covered Total %
statement 50 56 89.2
branch 13 22 59.0
condition 3 9 33.3
subroutine 7 7 100.0
pod 0 2 0.0
total 73 96 76.0


line stmt bran cond sub pod time code
1             package Catmandu::Store::File::Multi::Bag;
2              
3 2     2   1711 use Catmandu::Sane;
  2         5  
  2         16  
4              
5             our $VERSION = '1.16';
6              
7 2     2   548 use Moo;
  2         54  
  2         14  
8 2     2   792 use Catmandu::Util qw(:is);
  2         4  
  2         607  
9 2     2   17 use Catmandu::Logger;
  2         4  
  2         76  
10 2     2   12 use namespace::clean;
  2         5  
  2         17  
11              
12             extends 'Catmandu::Store::Multi::Bag';
13              
14             with 'Catmandu::FileBag';
15              
16             sub add {
17 1     1 0 1688 my ($self, $data) = @_;
18              
19             # Overwrite the Multi::Bag add an store each stream in the backend store
20              
21 1         3 my $rewind = 0;
22 1         3 my $id = $data->{_id};
23 1         3 my $stream = $data->{_stream};
24              
25 1         3 my $new_data = {};
26              
27             # By default try to add the data to all the stores
28 1         3 for my $store (@{$self->store->stores}) {
  1         8  
29 2         13 my $bag = $store->bag($self->name);
30 2 50       274 next unless $bag;
31              
32 2 100       8 if ($rewind) {
33              
34             # Rewind the stream after first use...
35 1 50       7 Catmandu::BadVal->throw("IO stream needs to seekable")
36             unless $stream->isa('IO::Seekable');
37 1         4 $stream->seek(0, 0);
38             }
39              
40 2         21 my $file = {_id => $id, _stream => $stream};
41 2         45 $bag->add($file);
42              
43 2         13 for (keys %$file) {
44 14 100       44 $new_data->{$_} = $file->{$_} unless exists $new_data->{$_};
45             }
46              
47 2         12 $rewind = 1;
48             }
49              
50             # Check if the returned record contains the minimum required fields
51             # (otherwise we have a File::Store implementation that doesn't inline
52             # update the passed $data in add($data))
53 1 50 33     19 if ( exists $new_data->{size}
      33        
54             && exists $new_data->{created}
55             && exists $new_data->{modified})
56             {
57             # all is ok
58             }
59             else {
60 0         0 $self->log->warn(
61             "$self doesn't inline update \$data in add(\$data) method");
62 0         0 $new_data = $self->get($id);
63             }
64              
65 1 50       4 if ($new_data) {
66 1         9 $data->{$_} = $new_data->{$_} for keys %$new_data;
67             }
68             else {
69 0         0 $self->log->error("can't find $id in $self!");
70             }
71              
72 1         20 1;
73             }
74              
75             sub upload {
76 4     4 0 11504 my ($self, $io, $id) = @_;
77              
78             # Upload in a FileStore should send data, in a normal Store it adds an
79             # empty record
80              
81 4         11 my $rewind;
82              
83 4         10 my $bytes = 0;
84              
85 4         8 for my $store (@{$self->store->stores}) {
  4         41  
86 8 50       116 if ($store->does('Catmandu::FileStore')) {
87 8         450 my $bag = $store->bag($self->name);
88 8 50       6068 next unless $bag;
89 8 100       25 if ($rewind) {
90              
91             # Rewind the stream after first use...
92 4 50       52 Catmandu::BadVal->throw("IO stream needs to seekable")
93             unless $io->isa('IO::Seekable');
94 4         28 $io->seek(0, 0);
95             }
96             $bytes
97 8   33     105 = $store->bag($self->name)->upload($io, $id)
98             || $self->log->error(
99             "failed to upload $id to " . $self->name);
100 8         39 $rewind = 1;
101             }
102             else {
103 0         0 my $bag = $store->bag($self->name);
104 0 0       0 next unless $bag;
105 0         0 $bag->add({_id => $id});
106             }
107             }
108              
109 4         62 return $bytes;
110             }
111              
112             1;
113              
114             __END__
115              
116             =pod
117              
118             =head1 NAME
119              
120             Catmandu::Store::File::Multi::Bag - Index of all "files" in a Catmandu::Store::File::Multi "folder"
121              
122             =head1 SYNOPSIS
123              
124             use Catmandu;
125              
126             my $store = Catmandu->store('File::Multi' , stores [
127             Catmandu->store('File::Simple', root => '/data1/files') ,
128             Catmandu->store('File::Simple', root => '/data1/files_copy') ,
129             ]);
130              
131             my $index = $store->index;
132              
133             # List all containers
134             $index->each(sub {
135             my $container = shift;
136              
137             print "%s\n" , $container->{_id};
138             });
139              
140             # Add a new folder
141             $index->add({_id => '1234'});
142              
143             # Delete a folder
144             $index->delete(1234);
145              
146             # Get a folder
147             my $folder = $index->get(1234);
148              
149             # Get the files in an folder
150             my $files = $index->files(1234);
151              
152             $files->each(sub {
153             my $file = shift;
154              
155             my $name = $file->{_id};
156             my $size = $file->{size};
157             my $content_type = $file->{content_type};
158             my $created = $file->{created};
159             my $modified = $file->{modified};
160              
161             $file->stream(IO::File->new(">/tmp/$name"), file);
162             });
163              
164             # Add a file
165             $files->upload(IO::File->new("<data.dat"),"data.dat");
166              
167             # Retrieve a file
168             my $file = $files->get("data.dat");
169              
170             # Stream a file to an IO::Handle
171             $files->stream(IO::File->new(">data.dat"),$file);
172              
173             # Delete a file
174             $files->delete("data.dat");
175              
176             # Delete a folders
177             $index->delete("1234");
178              
179             =head1 INHERITED METHODS
180              
181             This Catmandu::Bag implements:
182              
183             =over 3
184              
185             =item L<Catmandu::Bag>
186              
187             =item L<Catmandu::FileBag>
188              
189             =item L<Catmandu::Droppable>
190              
191             =back
192              
193             =cut