/[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 714 - (show annotations)
Tue Sep 26 12:47:52 2006 UTC (17 years, 7 months ago) by dpavlin
File size: 6548 byte(s)
 r1022@llin:  dpavlin | 2006-09-26 14:45:37 +0200
 make database in constructor (new) really optional (as documented :-)

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/) {
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} || $log->logconfess("no database?");
180
181 my $input = $args->{input} || '';
182
183 my $cache_file = "$cache_path/$database/$input/$id";
184 $cache_file =~ s#//#/#go;
185
186 $log->debug("using cache_file $cache_file");
187
188 if (-r $cache_file) {
189 my $ds_ref = retrieve($cache_file);
190 if ($ds_ref) {
191 $log->debug("cache hit: $cache_file");
192 if ($ds_ref->{'ds'}) {
193 return $ds_ref->{'ds'};
194 } else {
195 $log->warn("cache entry $cache_file corrupt. Use rm $cache_path/* to re-create it on next run!");
196 undef $self->{'path'};
197 }
198 }
199 } else {
200 #$log->warn("cache entry $cache_file doesn't exist");
201 return undef;
202 }
203
204 return undef;
205 }
206
207 =head2 save_ds
208
209 Store data_structure on disk.
210
211 $db->save_ds(
212 database => 'name',
213 input => 'name',
214 id => $ds->{000}->[0],
215 ds => $ds,
216 );
217
218 B<Totally broken, but fast.>
219
220 Depends on filename generated by C<load_ds>.
221
222 =cut
223
224 sub save_ds {
225 my $self = shift;
226
227 die "can't write to database in read_only mode!" if ($self->{'read_only'});
228
229 return unless($self->{'path'});
230
231 my $args = {@_};
232
233 my $log = $self->_get_logger;
234 $log->debug("save_ds arguments:", dump( \@_ ));
235
236 foreach my $f (qw/id ds/) {
237 $log->logconfess("need $f") unless (defined($args->{$f}));
238 }
239
240 my $database = $args->{database} || $self->{database};
241 $log->logconfess("can't find database name") unless (defined($database));
242
243 my $input = $args->{input} || '';
244
245 my $cache_file = $self->{path} . "/$database/$input/";
246 $cache_file =~ s#//#/#go;
247
248 mkpath($cache_file) unless (-d $cache_file);
249
250 $cache_file .= $args->{id};
251
252 $log->debug("creating storable cache file $cache_file");
253
254 return store {
255 ds => $args->{ds},
256 id => $args->{id},
257 }, $cache_file;
258
259 }
260
261 =head2 save_lookup
262
263 $db->save_lookup(
264 database => $database,
265 input => $input,
266 key => $key,
267 data => $lookup,
268 );
269
270 =cut
271
272 sub save_lookup {
273 my $self = shift;
274 my $args = {@_};
275
276 my $log = $self->_get_logger;
277
278 foreach my $r (qw/input key data/) {
279 $log->logconfess("need '$r'") unless defined($args->{$r});
280 }
281
282 my $database = $args->{database} || $self->{database} || $log->logconfess("no database?");
283
284 my $path = $self->{path} . "/lookup/$database/" . $args->{input};
285
286 mkpath($path) unless (-d $path);
287
288 $path .= "/" . $args->{key};
289
290 if (store $args->{data}, $path) {
291 $log->info("saved lookup $path");
292 return 1;
293 } else {
294 $log->logwarn("can't store lookup $database/", $args->{input}, "/", $args->{key}, " in $path: $!");
295 return undef;
296 }
297 }
298
299
300 =head1 AUTHOR
301
302 Dobrica Pavlinusic, C<< <dpavlin@rot13.org> >>
303
304 =head1 COPYRIGHT & LICENSE
305
306 Copyright 2005 Dobrica Pavlinusic, All Rights Reserved.
307
308 This program is free software; you can redistribute it and/or modify it
309 under the same terms as Perl itself.
310
311 =cut
312
313 1; # End of WebPAC::Store

  ViewVC Help
Powered by ViewVC 1.1.26