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

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

Parent Directory Parent Directory | Revision Log Revision Log


Revision 1.15 - (show annotations)
Thu Feb 20 20:19:13 2003 UTC (21 years, 4 months ago) by joko
Branch: MAIN
Changes since 1.14: +33 -4 lines
tried to get auto-disconnect working again - failed with that

1 ## ------------------------------------------------------------------------
2 ## $Id: Abstract.pm,v 1.14 2003/02/09 05:12:28 joko Exp $
3 ## ------------------------------------------------------------------------
4 ## $Log: Abstract.pm,v $
5 ## Revision 1.14 2003/02/09 05:12:28 joko
6 ## + quoting of strings used in sql-queries!
7 ##
8 ## Revision 1.13 2003/01/30 22:27:05 joko
9 ## + added new abstract methods
10 ##
11 ## Revision 1.12 2003/01/30 21:46:32 joko
12 ## + fixed behaviour of AUTOLOAD-method
13 ##
14 ## Revision 1.11 2003/01/20 16:43:18 joko
15 ## + better argument-property merging
16 ## + debugging-output !!!
17 ## + abstract-dummy 'sub createChildNode'
18 ##
19 ## Revision 1.10 2003/01/19 02:31:51 joko
20 ## + fix to 'sub AUTOLOAD'
21 ##
22 ## Revision 1.9 2002/12/19 16:30:23 joko
23 ## + added 'sub dropDb' and 'sub rebuildDb' as croakers for concrete implementations of methods in proper handlers
24 ##
25 ## Revision 1.8 2002/12/13 21:48:35 joko
26 ## + sub _abstract_function
27 ##
28 ## Revision 1.7 2002/12/05 07:57:48 joko
29 ## + now using Tie::SecureHash as a base for the COREHANDLE
30 ## + former public COREHANDLE becomes private _COREHANDLE now
31 ##
32 ## Revision 1.6 2002/12/03 15:52:24 joko
33 ## + fix/feature: if dispatching to deep core method fails (is not declared), try method at Data::Storage - level
34 ##
35 ## Revision 1.5 2002/12/01 22:19:33 joko
36 ## + just disconnect if COREHANDLE exists
37 ##
38 ## Revision 1.4 2002/12/01 04:45:38 joko
39 ## + sub eraseAll
40 ## + sub createDb
41 ##
42 ## Revision 1.3 2002/11/29 04:58:20 joko
43 ## + Storage::Result now uses the same dispatching mechanism like Storage::Handler
44 ##
45 ## Revision 1.2 2002/10/17 00:08:07 joko
46 ## + bugfixes regarding "deep recursion" stuff
47 ##
48 ## Revision 1.1 2002/10/10 03:44:07 cvsjoko
49 ## + new
50 ## ------------------------------------------------------------------------
51
52
53 package Data::Storage::Handler::Abstract;
54
55 use strict;
56 use warnings;
57
58 use base qw( DesignPattern::Object );
59
60
61 use Data::Dumper;
62 use Tie::SecureHash;
63 #use Data::Storage::Handler;
64 use Hash::Merge qw( merge );
65
66
67 # get logger instance
68 my $logger = Log::Dispatch::Config->instance;
69
70 #our $lock_info;
71
72 sub new {
73 my $invocant = shift;
74 my $class = ref($invocant) || $invocant;
75
76 # logging info about the actual handler called
77 $logger->debug( "$invocant->new( @_ )" );
78 #$logger->debug( __PACKAGE__ . "->" . "new()" );
79
80 # V1 - arguments become properties automagically / normal perl mode blessing
81 =pod
82 # autovivify passed-in arguments as future object attributes into to-be-blessed hash
83 my $self = { @_ };
84 # create object from blessed hash-reference
85 bless $self, $class;
86 =cut
87
88 #=pod
89 # V2 - maybe more convenient/secure? utilizing Damian Conway's Tie::SecureHash...
90 my $self = Tie::SecureHash->new(
91 $class,
92 # that's it:
93 'metainfo' => undef,
94 'lock_info' => undef,
95 '_COREHANDLE' => undef,
96 'meta' => undef,
97 'locator' => undef,
98 'dataStorageLayer' => undef,
99 'dbi' => undef,
100 # tries:
101 #'Data::Storage::Handler::Abstract::metainfo' => undef,
102 #'dataStorageLayer'
103 #'Data::Storage::Handler::Abstract::dataStorageLayer' => undef,
104 #'Data::Storage::Handler::Tangram::dataStorageLayer' => undef,
105 #'Data::Dumper::locator' => undef,
106 #$class . '::locator' => undef,
107 #'Data::Storage::Handler::Tangram::locator' => undef,
108 #'Data::Storage::Handler::DBI::locator' => undef,
109 #_protected => ,
110 #__private => ,
111 );
112 #=cut
113
114 # merge passed-in arguments to constructor as properties into already blessed secure object
115
116 # mungle arguments from array into hash - perl does the job ;)
117 #my %args = @_;
118 #my %args = ();
119
120 #print Dumper(@_);
121
122 # merge attributes one-by-one
123 # TODO: deep_copy? / merge_deep?
124 while (my $elemName = shift @_) {
125 #print "elemName: $elemName", "\n";
126 if (my $elemValue = shift @_) {
127 #print Dumper($elemValue);
128 #print "elemName=$elemName, elemValue=$elemValue", "\n";
129 $self->{$elemName} = $elemValue;
130 }
131 #$self->{$_} = $args{$_};
132 #$self->{$_} = $args{$_};
133 }
134
135 # V3 - rolling our own security (just for {COREHANDLE} - nothing else) - nope, Tie::SecureHash works wonderful
136 #my $self = { @_ };
137 #bless $self, $class;
138
139
140
141 # handle meta data
142 #my $metainfo = $self->getMetaInfo($class);
143 my $metainfo = $self->getMetaInfo();
144 if (!$metainfo->{disconnectMethod}) { $metainfo->{disconnectMethod} = 'disconnect'; }
145 # type?
146 $invocant =~ s/Data::Storage::Handler:://;
147 $metainfo->{type} = $invocant;
148
149 # direct accessible (non-protected) properties ( was: my $self = { }; )
150 $self->{metainfo} = $metainfo;
151
152 return $self;
153 }
154
155
156 # TODO: use NEXT.pm inside this mechanism (to avoid repetitions...)
157 sub AUTOLOAD {
158
159 # recursion problem to be avoided here!!!
160
161 # - problem: we get recursion-hangs!!! => perl stops with ...
162 # "Deep recursion on subroutine "Data::Storage::Handler::Abstract::AUTOLOAD" at [...]/libs/Data/Storage.pm line 38."
163
164 # - when: if we log to ourselves as a storage-implementation (e.g. via Log::Dispatch::Tangram)
165 # - why: debug-messages are on a very low level including every data-operation to "Data::Storage(::Handler::X)",
166 # so e.g. a "$storage->insert" would trigger another "$storage->insert" itself
167 # which leads to a infinite recursion loop (deep recursion)
168 # - solution: locks! (by Hack or (maybe) via Perl "local"s)
169
170 my $self = shift;
171
172 our $AUTOLOAD;
173 #return if $AUTOLOAD =~ m/::DESTROY$/;
174
175 # find out methodname
176 my $methodname = $AUTOLOAD;
177 $methodname =~ s/^.*:://;
178
179 #print "method: $methodname", "\n";
180
181 # TODO: document this! handler-private methods listed here will not be triggered (internal use)
182 # in this case, "exists" is a method reserved for Tie::SecureHash,
183 # which encapsulates the perl data structure (HASH) under this object
184 # this is to prevent deep recursion's
185 return if lc $methodname eq 'exists';
186
187 #print "$methodname - 1", "\n";
188
189 # TODO: enhance logging/debugging
190 #if (!$self->exists('COREHANDLE')) { return; }
191
192 # handle locking (hack)
193 if ($self->can('exists') && $self->exists('lock_info') && $self->{lock_info}->{last_method} && $methodname eq $self->{lock_info}->{last_method}) {
194 $self->{lock_info}->{log_lock} = 1;
195 } else {
196 $self->{lock_info}->{log_lock} = 0;
197 }
198 $self->{lock_info}->{last_method} = $methodname;
199
200 #print "$methodname - 2", "\n";
201
202 #print Dumper($self);
203 #exit;
204
205 # get corehandle instance from underlying handler
206 my $core = $self->getCOREHANDLE();
207
208 # test for COREHANDLE
209 #if (!$self->{_COREHANDLE}) {
210 #=pod
211 #if (!$self->exists('_COREHANDLE')) {
212 #if (!$self->{_COREHANDLE}) {
213 if (!$core) {
214
215 #print Dumper($self);
216 #exit;
217
218 my $handlertype = $self->{metainfo}->{type};
219 $handlertype ||= '';
220
221 my $err_msg_core = __PACKAGE__ . "[$handlertype]" . ": " . "COREHANDLE is undefined while trying to execute method \"$methodname\"";
222
223 #print $err_msg_core, "\n";
224
225 #if ($self->exists('lock_info') && !$self->{lock_info}->{log_lock}) {
226 $logger->error( $err_msg_core );
227 #}
228
229 return;
230
231 }
232 #=cut
233
234 #print "$methodname - 3", "\n";
235
236 # try to dispatch method-call to Storage::Handler::*
237 #if ($self->can($methodname)) {
238 #$logger->debug( __PACKAGE__ . "[$self->{metainfo}->{type}]" . "->" . $methodname . "(@_)" );
239 #my $res = $self->$methodname(@_);
240 #if ($res) { return $res; }
241 #}
242
243 #print "$methodname - 4", "\n";
244
245 # try to dispatch method-call to COREHANDLE
246 # was:
247 #my $core = $self->{_COREHANDLE};
248 # is:
249 #my $core = $self->getCOREHANDLE();
250
251 #print Dumper($core);
252 #exit;
253
254 # was:
255 #if ($self->{_COREHANDLE}->can($methodname) || $self->{_COREHANDLE}->can("AUTOLOAD")) {
256 # is:
257 if ($core->can($methodname) || $core->can("AUTOLOAD")) {
258 #$logger->debug( __PACKAGE__ . "->" . $methodname . " (AUTOLOAD)" );
259 #$lock_AUTOLOAD = 1 if ($methodname eq 'insert');
260 if (!$self->{lock_info}->{log_lock}) {
261 #print "method: $methodname", "\n";
262 $logger->debug( __PACKAGE__ . "[$self->{metainfo}->{type}]" . "->" . $methodname . "(@_)" );
263 } else {
264 # AUTOLOAD - sub is locked to prevent deep recursions if (e.g.) db-inserts cause log-actions to same db itself
265 }
266 #$lock_AUTOLOAD = 0;
267 #$logger->log( level => 'debug', message => __PACKAGE__ . "->" . $methodname . " (AUTOLOAD)" );
268
269 #print "calling: $methodname", "\n";
270
271 # method calls making it until here will get dispatched to the proper handler
272 return $core->$methodname(@_);
273
274 } elsif ($self->can($methodname)) {
275 # try to call specified method inside our or inherited module(s) scope(s)
276 return $self->$methodname(@_);
277 }
278
279 }
280
281 sub DESTROY {
282 my $self = shift;
283
284 return;
285
286 $logger->debug( __PACKAGE__ . "[$self->{metainfo}->{type}]" . "->DESTROY" );
287
288 my $disconnectMethod = $self->{metainfo}->{disconnectMethod};
289 print "meth: ", $disconnectMethod, "\n";
290
291 #$disconnectMethod && $self->{_COREHANDLE} && ( $self->{_COREHANDLE}->$disconnectMethod() );
292 $self->{_COREHANDLE}->$disconnectMethod();
293 #$self->$disconnectMethod();
294
295 #my $core1 = $self->getCOREHANDLE() if $self->can('getCOREHANDLE');
296 #$core1->$disconnectMethod();
297
298 return;
299
300 print "DESTROY-1", "\n";
301 #if ($self->{__COREHANDLE}) {
302 #if ($self->exists('_COREHANDLE')) {
303
304 # get corehandle instance from underlying handler
305 my $core;
306 $core = $self->getCOREHANDLE() if $self->can('getCOREHANDLE');
307
308 #if ($self->{STORAGEHANDLE}) {
309 if ($core) {
310 print "DESTROY-2", "\n";
311 $logger->debug( __PACKAGE__ . "[$self->{metainfo}->{type}]" . "->DESTROY" );
312
313 my $disconnectMethod = $self->{metainfo}->{disconnectMethod};
314
315 # call "disconnect" or alike on COREHANDLE
316 # was: $self->{COREHANDLE}->disconnect();
317 $disconnectMethod && $self->{_COREHANDLE} && ( $self->{_COREHANDLE}->$disconnectMethod() );
318
319 undef $self->{_COREHANDLE};
320 }
321 }
322
323 sub _typeCheck2 {
324 my $type = shift;
325 print "type: $type";
326 eval("use Data::Storage::$type;");
327 }
328
329
330 # ====================================================
331 # PUBLIC METHODS
332 # ====================================================
333
334 sub existsChildNode {
335 my $self = shift;
336 my $nodename = shift;
337
338 # TODO: don't use $self->{meta}->{childnodes} directly in here
339 # get it returned from $self->getChildNodes()!!!
340
341 $logger->debug( __PACKAGE__ . "->existsChildNode( nodename=$nodename )" );
342 $self->getChildNodes() unless $self->{meta}->{childnodes};
343
344 # quote this, it might contain meta characters which don't work in a regex
345 $nodename = quotemeta($nodename);
346
347 # trace
348 #print Dumper($self->{meta});
349 #print "nodename: $nodename", "\n";
350
351 # FIXME: use "/i" only on win32-systems!
352 my $result = grep(m/$nodename/i, @{$self->{meta}->{childnodes}});
353
354 return $result;
355 }
356
357 sub connect_tmp {
358
359 # my $self = shift;
360 # my $connectionString = shift;
361 # # todo: patch connectionString to $args
362 # _typeCheck($self->{args}{type});
363
364 }
365
366
367 # ====================================================
368 # CONCRETE METHOD DUMMIES (croaking via "$logger" by calling "_abstract_function")
369 # ====================================================
370
371 # TODO:
372 # - abstract "abstract methods" to list/hash to be used in AUTOLOAD
373 # e.g.: my @ABSTRACT_METHODS = (qw( connect sendCommand getChildNodes ));
374 # use Class::XYZ (Construct)
375 # - build them via anonymous subs
376 # - introduce them via symbols
377
378 sub getCOREHANDLE {
379 my $self = shift;
380 $self->_abstract_function('getCOREHANDLE');
381 }
382
383 sub sendCommand {
384 my $self = shift;
385 $self->_abstract_function('sendCommand');
386 }
387
388 sub createChildNode {
389 my $self = shift;
390 $self->_abstract_function('createChildNode');
391 }
392
393 sub existsChildNode_tmp {
394 my $self = shift;
395 $self->_abstract_function('existsChildNode');
396 }
397
398 sub getChildNodes {
399 my $self = shift;
400 $self->_abstract_function('getChildNodes');
401 }
402
403 sub configureCOREHANDLE {
404 my $self = shift;
405 $self->_abstract_function('configureCOREHANDLE');
406 }
407
408 sub getMetaInfo {
409 my $self = shift;
410 $self->_abstract_function('getMetaInfo');
411 return;
412 }
413
414 sub getListUnfiltered {
415 my $self = shift;
416 $self->_abstract_function('getListUnfiltered');
417 return;
418 }
419
420 sub getListFiltered {
421 my $self = shift;
422 $self->_abstract_function('getListFiltered');
423 return;
424 }
425
426 sub sendQuery {
427 my $self = shift;
428 $self->_abstract_function('sendQuery');
429 return;
430 }
431
432 sub connect {
433 my $self = shift;
434 $self->_abstract_function('connect');
435 return;
436 }
437
438 sub testIntegrity {
439 my $self = shift;
440 $self->_abstract_function('testIntegrity');
441 return;
442 }
443
444 sub quoteSql {
445 my $self = shift;
446 $self->_abstract_function('quoteSql');
447 return;
448 }
449
450 sub eraseAll {
451 my $self = shift;
452 $self->_abstract_function('eraseAll');
453 return;
454 }
455
456 sub createDb {
457 my $self = shift;
458 $self->_abstract_function('createDb');
459 return;
460 }
461
462 sub dropDb {
463 my $self = shift;
464 $self->_abstract_function('dropDb');
465 return;
466 }
467
468 sub rebuildDb {
469 my $self = shift;
470 $self->_abstract_function('rebuildDb');
471 return;
472 }
473
474 sub getDbName {
475 my $self = shift;
476 $self->_abstract_function('getDbName');
477 return;
478 }
479
480 sub testAvailability {
481 my $self = shift;
482 $self->_abstract_function('testAvailability');
483 return;
484 }
485
486 sub isConnected {
487 my $self = shift;
488 $self->_abstract_function('isConnected');
489 return;
490 }
491
492 sub testDsn {
493 my $self = shift;
494 $self->_abstract_function('testDsn');
495 return;
496 }
497
498 1;

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