/[webpac2]/trunk/lib/WebPAC/Store.pm
This is repository of my old source code which isn't updated any more. Go to git.rot13.org for current projects!
ViewVC logotype

Contents of /trunk/lib/WebPAC/Store.pm

Parent Directory Parent Directory | Revision Log Revision Log


Revision 713 - (show annotations)
Tue Sep 26 12:42:49 2006 UTC (17 years, 7 months ago) by dpavlin
File size: 6578 byte(s)
 r1020@llin:  dpavlin | 2006-09-26 14:40:34 +0200
 refactored WebPAC::Store

1 package WebPAC::Store;
2
3 use warnings;
4 use strict;
5
6 use base 'WebPAC::Common';
7 use Storable;
8 use File::Path;
9 use Data::Dump qw/dump/;
10
11 =head1 NAME
12
13 WebPAC::Store - Store WebPAC data on disk
14
15 =head1 VERSION
16
17 Version 0.11
18
19 =cut
20
21 our $VERSION = '0.11';
22
23 =head1 SYNOPSIS
24
25 This module provides disk storage for normalised data and lookups.
26
27 It is one of newer components of WebPAC, so it will change from time to
28 time.
29
30 I will try to keep backward compatiblity by providing multiple back-ends,
31 but this can't be garanteed. In other words, don't delete your input
32 databases just yet :-)
33
34 This has additional advantage. I can create single place to plugin other
35 file formats which provide better performance for particular type of data.
36
37 For now, this is a prototype version.
38
39 use WebPAC::Store;
40
41 my $foo = WebPAC::Store->new();
42 ...
43
44 =head1 FUNCTIONS
45
46 =head2 new
47
48 Create new normalised database object
49
50 my $db = new WebPAC::Store(
51 path => '/path/to/cache/ds/',
52 database => 'name',
53 read_only => 1,
54 );
55
56 Optional parameter C<path> defines path to directory
57 in which cache file for C<data_structure> call will be created.
58
59 If called with C<read_only> it will not disable caching if
60 called without write permission (but will die on C<save_ds>).
61
62 Optional parametar C<database> will be used used as subdirectory in path if no
63 database in specified when calling other functions.
64
65 =cut
66
67 sub new {
68 my $class = shift;
69 my $self = {@_};
70 bless($self, $class);
71
72 my $log = $self->_get_logger();
73
74 foreach my $p (qw/path database/) {
75 $log->logconfess("need $p") unless ($self->{$p});
76 }
77
78 $self->path( $self->{'path'} );
79
80 $self ? return $self : return undef;
81 }
82
83 =head2 path
84
85 Check if specified cache directory exist, and if not, disable caching.
86
87 $db->path('./cache/ds/');
88
89 If you pass false or zero value to this function, it will disable
90 cacheing.
91
92 You can also call this function to get current cache path.
93
94 my $cache_path = $db->path;
95
96 =cut
97
98 sub path {
99 my $self = shift;
100
101 my $dir = shift;
102
103 return $self->{path} unless defined($dir);
104
105 my $log = $self->_get_logger();
106
107 if ($dir) {
108 my $msg;
109 if (! -e $dir) {
110 if ($self->{'read_only'}) {
111 $msg = "doesn't exist";
112 } else {
113 $log->info("creating $dir");
114 mkpath $dir;
115 }
116 } elsif (! -d $dir) {
117 $msg = "is not directory";
118 } elsif (! -w $dir) {
119 $msg = "not writable" unless ($self->{'read_only'});
120 }
121
122 if ($msg) {
123 $log->warn("cache path $dir $msg, disabling...");
124 undef $self->{'path'};
125 } else {
126 $log->debug("using cache dir $dir");
127 $self->{'path'} = $dir;
128 }
129 } else {
130 $log->debug("disabling cache");
131 undef $self->{'path'};
132 }
133 }
134
135 =head2 load_ds
136
137 Retrive from disk one data_structure records usually using field 000 as key
138
139 my $ds = $db->load_ds(
140 database => 'ps',
141 input => 'name',
142 id => 42,
143 );
144
145 This function will also perform basic sanity checking on returned
146 data and disable caching if data is corrupted (or changed since last
147 update).
148
149 C<input> is used to differenciate different source input databases
150 which are indexed in same database.
151
152 C<database> if B<optional> argument which will override database name used when creating
153 C<WebPAC::Store> object (for simple retrival from multiple databases).
154
155 Returns hash or undef if cacheing is disabled or unavailable.
156
157 =cut
158
159 sub load_ds {
160 my $self = shift;
161
162 my $log = $self->_get_logger;
163
164 my $cache_path = $self->{'path'};
165
166 if (! $cache_path) {
167 $log->warn("path not set, ignoring load_ds");
168 return;
169 }
170
171 $log->logconfess("arguments for load_ds must be HASH") unless (ref(\@_) eq 'ARRAY' && ($#_ % 2 == 1));
172
173 my $args = {@_};
174 my $id = $args->{id};
175
176 $log->logconfess("got hash, but without id") unless (defined($id));
177 $log->logconfess("got hash, but id [$id] isn't number") unless ($id =~ /^\d+$/);
178
179 my $database = $args->{database} || $self->{database};
180 my $input = $args->{input} || '';
181
182 $log->logconfess("can't find database name") unless ($database);
183
184 my $cache_file = "$cache_path/$database/$input/$id";
185 $cache_file =~ s#//#/#go;
186
187 $log->debug("using cache_file $cache_file");
188
189 if (-r $cache_file) {
190 my $ds_ref = retrieve($cache_file);
191 if ($ds_ref) {
192 $log->debug("cache hit: $cache_file");
193 if ($ds_ref->{'ds'}) {
194 return $ds_ref->{'ds'};
195 } else {
196 $log->warn("cache entry $cache_file corrupt. Use rm $cache_path/* to re-create it on next run!");
197 undef $self->{'path'};
198 }
199 }
200 } else {
201 #$log->warn("cache entry $cache_file doesn't exist");
202 return undef;
203 }
204
205 return undef;
206 }
207
208 =head2 save_ds
209
210 Store data_structure on disk.
211
212 $db->save_ds(
213 database => 'name',
214 input => 'name',
215 id => $ds->{000}->[0],
216 ds => $ds,
217 );
218
219 B<Totally broken, but fast.>
220
221 Depends on filename generated by C<load_ds>.
222
223 =cut
224
225 sub save_ds {
226 my $self = shift;
227
228 die "can't write to database in read_only mode!" if ($self->{'read_only'});
229
230 return unless($self->{'path'});
231
232 my $args = {@_};
233
234 my $log = $self->_get_logger;
235 $log->debug("save_ds arguments:", dump( \@_ ));
236
237 foreach my $f (qw/id ds/) {
238 $log->logconfess("need $f") unless (defined($args->{$f}));
239 }
240
241 my $database = $args->{database} || $self->{database};
242 $log->logconfess("can't find database name") unless ($database);
243
244 my $input = $args->{input} || '';
245
246 my $cache_file = $self->{path} . "/$database/$input/";
247 $cache_file =~ s#//#/#go;
248
249 mkpath($cache_file) unless (-d $cache_file);
250
251 $cache_file .= $args->{id};
252
253 $log->debug("creating storable cache file $cache_file");
254
255 return store {
256 ds => $args->{ds},
257 id => $args->{id},
258 }, $cache_file;
259
260 }
261
262 =head2 save_lookup
263
264 $db->save_lookup(
265 database => $database,
266 input => $input,
267 key => $key,
268 data => $lookup,
269 );
270
271 =cut
272
273 sub save_lookup {
274 my $self = shift;
275 my $args = {@_};
276
277 my $log = $self->_get_logger;
278
279 foreach my $r (qw/input key data/) {
280 $log->logconfess("need '$r'") unless defined($args->{$r});
281 }
282
283 my $database = $args->{database} || $self->{database} || $log->logconfess("no database?");
284
285 my $path = $self->{path} . "/lookup/$database/" . $args->{input};
286
287 mkpath($path) unless (-d $path);
288
289 $path .= "/" . $args->{key};
290
291 if (store $args->{data}, $path) {
292 $log->info("saved lookup $path");
293 return 1;
294 } else {
295 $log->logwarn("can't store lookup $database/", $args->{input}, "/", $args->{key}, " in $path: $!");
296 return undef;
297 }
298 }
299
300
301 =head1 AUTHOR
302
303 Dobrica Pavlinusic, C<< <dpavlin@rot13.org> >>
304
305 =head1 COPYRIGHT & LICENSE
306
307 Copyright 2005 Dobrica Pavlinusic, All Rights Reserved.
308
309 This program is free software; you can redistribute it and/or modify it
310 under the same terms as Perl itself.
311
312 =cut
313
314 1; # End of WebPAC::Store

  ViewVC Help
Powered by ViewVC 1.1.26