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

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

Parent Directory Parent Directory | Revision Log Revision Log | View Patch Patch

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

Legend:
Removed from v.1.5  
changed lines
  Added in v.1.19

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