/[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.19 - (show annotations)
Wed Jun 25 22:53:58 2003 UTC (21 years ago) by joko
Branch: MAIN
CVS Tags: HEAD
Changes since 1.18: +5 -2 lines
don't disconnect automagically

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

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