/[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.17 - (show annotations)
Tue May 13 07:58:49 2003 UTC (21 years, 1 month ago) by joko
Branch: MAIN
Changes since 1.16: +14 -2 lines
fix: die if methodname is empty
fixes to log-string

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

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