/[cvs]/nfo/perl/libs/Data/Storage.pm
ViewVC logotype

Contents of /nfo/perl/libs/Data/Storage.pm

Parent Directory Parent Directory | Revision Log Revision Log


Revision 1.16 - (show annotations)
Mon Jan 20 16:52:13 2003 UTC (21 years, 5 months ago) by joko
Branch: MAIN
Changes since 1.15: +54 -8 lines
+ now using 'DesignPattern::Object' to create a new 'Data::Storage::Handler::Xyz' on demand - before we did this in a hand-rolled fashion

1 ## ------------------------------------------------------------------------
2 ##
3 ## $Id: Storage.pm,v 1.15 2003/01/19 03:12:59 joko Exp $
4 ##
5 ## Copyright (c) 2002 Andreas Motl <andreas.motl@ilo.de>
6 ##
7 ## See COPYRIGHT section in pod text below for usage and distribution rights.
8 ##
9 ## ------------------------------------------------------------------------
10 ##
11 ## $Log: Storage.pm,v $
12 ## Revision 1.15 2003/01/19 03:12:59 joko
13 ## + modified header
14 ## - removed pod-documentation - now in 'Storage.pod'
15 ##
16 ## Revision 1.14 2002/12/19 16:27:59 joko
17 ## - moved 'sub dropDb' to Data::Storage::Handler::DBI
18 ##
19 ## Revision 1.13 2002/12/17 21:54:12 joko
20 ## + feature when using Tangram:
21 ## + what? each object created should delivered with a globally(!?) unique identifier (GUID) besides the native tangram object id (OID)
22 ## + patched Tangram::Storage (jonen)
23 ## + enhanced Data::Storage::Schema::Tangram (joko)
24 ## + enhanced Data::Storage::Handler::Tangram 'sub getObjectByGuid' (jonen)
25 ## + how?
26 ## + each concrete (non-abstract) class gets injected with an additional field/property called 'guid' - this is done (dynamically) on schema level
27 ## + this property ('guid') gets filled on object creation/insertion from 'sub Tangram::Storage::_insert' using Data::UUID from CPAN
28 ## + (as for now) this property can get accessed by calling 'getObjectByGuid' on the already known storage-handle used throughout the application
29 ##
30 ## Revision 1.12 2002/12/12 02:50:15 joko
31 ## + this now (unfortunately) needs DBI for some helper functions
32 ## + TODO: these have to be refactored to another scope! (soon!)
33 ##
34 ## Revision 1.11 2002/12/11 06:53:19 joko
35 ## + updated pod
36 ##
37 ## Revision 1.10 2002/12/07 03:37:23 joko
38 ## + updated pod
39 ##
40 ## Revision 1.9 2002/12/01 22:15:45 joko
41 ## - sub createDb: moved to handler
42 ##
43 ## Revision 1.8 2002/11/29 04:48:23 joko
44 ## + updated pod
45 ##
46 ## Revision 1.7 2002/11/17 06:07:18 joko
47 ## + creating the handler is easier than proposed first - for now :-)
48 ## + sub testAvailability
49 ##
50 ## Revision 1.6 2002/11/09 01:04:58 joko
51 ## + updated pod
52 ##
53 ## Revision 1.5 2002/10/29 19:24:18 joko
54 ## - reduced logging
55 ## + added some pod
56 ##
57 ## Revision 1.4 2002/10/27 18:35:07 joko
58 ## + added pod
59 ##
60 ## Revision 1.3 2002/10/25 11:40:37 joko
61 ## + enhanced robustness
62 ## + more logging for debug-levels
63 ## + sub dropDb
64 ##
65 ## Revision 1.2 2002/10/17 00:04:29 joko
66 ## + sub createDb
67 ## + sub isConnected
68 ## + bugfixes regarding "deep recursion" stuff
69 ##
70 ## Revision 1.1 2002/10/10 03:43:12 cvsjoko
71 ## + new
72 ## ------------------------------------------------------------------------
73
74
75 BEGIN {
76 $Data::Storage::VERSION = 0.03;
77 }
78
79 package Data::Storage;
80
81 use strict;
82 use warnings;
83
84 use Data::Dumper;
85 # FIXME: wipe out!
86 use DBI;
87
88 use Data::Storage::Locator;
89 use DesignPattern::Object;
90
91
92 # TODO: actually implement level (integrate with Log::Dispatch)
93 my $TRACELEVEL = 0;
94
95 # get logger instance
96 my $logger = Log::Dispatch::Config->instance;
97
98 sub new {
99 my $invocant = shift;
100 my $class = ref($invocant) || $invocant;
101 #my @args = normalizeArgs(@_);
102
103 my $arg_locator = shift;
104 my $arg_options = shift;
105
106 if (!$arg_locator) {
107 $logger->critical( __PACKAGE__ . "->new: No locator passed in!" );
108 return;
109 }
110
111 #my $self = { STORAGEHANDLE => undef, @_ };
112 my $self = { STORAGEHANDLE => undef, locator => $arg_locator, options => $arg_options };
113 #$logger->debug( __PACKAGE__ . "[$self->{locator}->{type}]" . "->new(@_)" );
114 $logger->debug( __PACKAGE__ . "[$arg_locator->{type}]" . "->new(@_)" );
115 return bless $self, $class;
116 }
117
118 sub AUTOLOAD {
119
120 # since this is a core function acting as dispatcher to $self->{STORAGEHANDLE},
121 # some sophisticated handling and filtering is needed to avoid things like
122 # - Deep recursion on subroutine "Data::Storage::AUTOLOAD"
123 # - Deep recursion on subroutine "Data::Storage::Handler::Abstract::AUTOLOAD"
124 # - Deep recursion on anonymous subroutine at [...]
125 # we also might filter log messages caused by logging to itself in "advanced logging of AUTOLOAD calls"
126
127 my $self = shift;
128 our $AUTOLOAD;
129
130 # ->DESTROY would - if not declared - trigger an AUTOLOAD also
131 return if $AUTOLOAD =~ m/::DESTROY$/;
132
133 my $method = $AUTOLOAD;
134 $method =~ s/^.*:://;
135
136 # advanced logging of AUTOLOAD calls ...
137 # ... nice but do it only when TRACING (TODO) is enabled
138 my $logstring = "";
139 $logstring .= __PACKAGE__ . "[$self->{locator}->{type}]" . "->" . $method;
140 #print "count: ", $#_, "\n";
141 #$logstring .= Dumper(@_) if ($#_ != -1);
142 my $tabcount = int( (80 - length($logstring)) / 10 );
143 $logstring .= "\t" x $tabcount . "(AUTOLOAD)";
144 # TODO: only ok if logstring doesn't contain
145 # e.g. "Data::Storage[Tangram]->insert(SystemEvent=HASH(0x5c0034c)) (AUTOLOAD)"
146 # but that would be _way_ too specific as long as we don't have an abstract handler for this ;)
147 if ($TRACELEVEL) {
148 $logger->debug( $logstring );
149 #print join('; ', @_);
150 }
151
152 # filtering AUTOLOAD calls and first-time-touch of the actual storage impl
153 if ($self->_filter_AUTOLOAD($method)) {
154 $self->_accessStorage();
155 if ($self->{STORAGEHANDLE}) {
156 return $self->{STORAGEHANDLE}->$method(@_);
157 } else {
158 $logger->critical( __PACKAGE__ . "->AUTOLOAD: ERROR: " . $logstring );
159 return;
160 }
161 }
162
163 }
164
165 sub _filter_AUTOLOAD {
166 my $self = shift;
167 my $method = shift;
168 if ($self->{options}->{protected}) {
169 if ($method eq 'disconnect') {
170 return;
171 }
172 }
173 return 1;
174 }
175
176
177 sub normalizeArgs {
178 my %args = @_;
179 if (!$args{dsn} && $args{meta}{dsn}) {
180 $args{dsn} = $args{meta}{dsn};
181 }
182 my @result = %args;
183 return @result;
184 }
185
186 sub _accessStorage {
187 my $self = shift;
188 # TODO: to some tracelevel!
189 if ($TRACELEVEL) {
190 $logger->debug( __PACKAGE__ . "[$self->{locator}->{type}]" . "->_accessStorage()" );
191 }
192 if (!$self->{STORAGEHANDLE}) {
193 return $self->_createStorageHandle();
194 }
195 }
196
197 sub _createStorageHandle1 {
198 my $self = shift;
199 my $type = $self->{locator}->{type};
200 $logger->debug( __PACKAGE__ . "[$type]" . "->_createStorageHandle()" );
201
202 my $pkg = "Data::Storage::Handler::" . $type . "";
203
204 # try to load perl module at runtime
205 my $evalstr = "use $pkg;";
206 eval($evalstr);
207 if ($@) {
208 $logger->error( __PACKAGE__ . "[$type]" . "->_createStorageHandle(): $@" );
209 return;
210 }
211
212 # build up some additional arguments to pass on
213 #my @args = %{$self->{locator}};
214 my @args = ();
215
216 # - create new storage handle object
217 # - propagate arguments to handler
218 # - pass locator by reference to be able to store status- or meta-information in it
219 $self->{STORAGEHANDLE} = $pkg->new( locator => $self->{locator}, @args );
220
221 }
222
223 sub _createStorageHandle {
224 my $self = shift;
225 my $type = $self->{locator}->{type};
226 $logger->debug( __PACKAGE__ . "[$type]" . "->_createStorageHandle()" );
227
228 #print Dumper($self);
229 #exit;
230
231 my $pkg = "Data::Storage::Handler::" . $type . "";
232
233 # try to load perl module at runtime
234 =pod
235 my $evalstr = "use $pkg;";
236 eval($evalstr);
237 if ($@) {
238 $logger->error( __PACKAGE__ . "[$type]" . "->_createStorageHandle(): $@" );
239 return;
240 }
241
242 # build up some additional arguments to pass on
243 #my @args = %{$self->{locator}};
244 my @args = ();
245
246 # - create new storage handle object
247 # - propagate arguments to handler
248 # - pass locator by reference to be able to store status- or meta-information in it
249 $self->{STORAGEHANDLE} = $pkg->new( locator => $self->{locator}, @args );
250 =cut
251
252 $self->{STORAGEHANDLE} = DesignPattern::Object->fromPackage( $pkg, locator => $self->{locator} );
253 return 1;
254
255 }
256
257 sub addLogDispatchHandler {
258
259 my $self = shift;
260 my $name = shift;
261 my $package = shift;
262 my $logger1 = shift;
263 my $objectCreator = shift;
264
265 #$logger->add( Log::Dispatch::Tangram->new( name => $name,
266 $logger->add( $package->new( name => $name,
267 #min_level => 'debug',
268 min_level => 'info',
269 storage => $self,
270 objectCreator => $objectCreator,
271 fields => {
272 message => 'usermsg',
273 timestamp => 'stamp',
274 level => 'level',
275 name => 'code',
276 },
277 filter_patterns => [ '->insert\(SystemEvent=' ],
278 #filter_patterns => [ 'SystemEvent' ],
279
280 #format => '[%d] [%p] %m%n',
281 ) );
282
283 }
284
285 sub removeLogDispatchHandler {
286 my $self = shift;
287 my $name = shift;
288 #my $logger = shift;
289 $logger->remove($name);
290 }
291
292 =pod
293 sub getDbName {
294 my $self = shift;
295 my $dsn = $self->{locator}->{dbi}->{dsn};
296 $dsn =~ m/database=(.+?);/;
297 my $database_name = $1;
298 return $database_name;
299 }
300
301 sub testAvailability {
302 my $self = shift;
303 my $status = $self->testDsn();
304 $self->{locator}->{status}->{available} = $status;
305 return $status;
306 }
307
308 sub isConnected {
309 my $self = shift;
310 # TODO: REVIEW!
311 return 1 if $self->{STORAGEHANDLE};
312 }
313
314 sub testDsn {
315 my $self = shift;
316 my $dsn = $self->{locator}->{dbi}->{dsn};
317 my $result;
318 if ( my $dbh = DBI->connect($dsn, '', '', {
319 PrintError => 0,
320 } ) ) {
321
322 # TODO: REVIEW
323 $dbh->disconnect();
324
325 return 1;
326 } else {
327 $logger->warning( __PACKAGE__ . "[$self->{locator}->{type}]" . "->testDsn(): " . "DBI-error: " . $DBI::errstr );
328 }
329 }
330 =cut
331
332 1;
333 __END__

MailToCvsAdmin">MailToCvsAdmin
ViewVC Help
Powered by ViewVC 1.1.26 RSS 2.0 feed