/[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.10 - (show annotations)
Sun Jan 19 02:31:51 2003 UTC (21 years, 5 months ago) by joko
Branch: MAIN
Changes since 1.9: +19 -7 lines
+ fix to 'sub AUTOLOAD'

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

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