/[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.16 - (show annotations)
Fri Apr 18 16:07:53 2003 UTC (21 years, 2 months ago) by joko
Branch: MAIN
Changes since 1.15: +9 -3 lines
just use logger if instantiation successed

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

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