/[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.17 - (show annotations)
Thu Jan 30 21:42:22 2003 UTC (21 years, 5 months ago) by joko
Branch: MAIN
Changes since 1.16: +9 -4 lines
+ minor update: renamed method

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

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