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

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

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

revision 1.1 by cvsjoko, Thu Oct 10 03:43:12 2002 UTC revision 1.5 by joko, Tue Oct 29 19:24:18 2002 UTC
# Line 1  Line 1 
1  #################################  # $Id$
2    #
3    # Copyright (c) 2002  Andreas Motl <andreas.motl@ilo.de>
4  #  #
5  #  $Id$  # See COPYRIGHT section in pod text below for usage and distribution rights.
6    #
7    #################################
8  #  #
9  #  $Log$  #  $Log$
10    #  Revision 1.5  2002/10/29 19:24:18  joko
11    #  - reduced logging
12    #  + added some pod
13    #
14    #  Revision 1.4  2002/10/27 18:35:07  joko
15    #  + added pod
16    #
17    #  Revision 1.3  2002/10/25 11:40:37  joko
18    #  + enhanced robustness
19    #  + more logging for debug-levels
20    #  + sub dropDb
21    #
22    #  Revision 1.2  2002/10/17 00:04:29  joko
23    #  + sub createDb
24    #  + sub isConnected
25    #  + bugfixes regarding "deep recursion" stuff
26    #
27  #  Revision 1.1  2002/10/10 03:43:12  cvsjoko  #  Revision 1.1  2002/10/10 03:43:12  cvsjoko
28  #  + new  #  + new
29  #  #
 #  
30  #################################  #################################
31    
32    # aim_V1: should encapsulate Tangram, DBI, DBD::CSV and LWP:: to access them in an unordinary way ;)
33    # aim_V2: introduce a generic layered structure, refactor *SUBLAYER*-stuff, make (e.g.) this possible:
34    #               - Perl Data::Storage[DBD::CSV]  ->  Perl LWP::  ->  Internet HTTP/FTP/*  ->  Host Daemon  ->  csv-file
35    
36    BEGIN {
37    $Data::Storage::VERSION = 0.01;
38    }
39    
40    
41    =head1 NAME
42    
43    Data::Storage - Interface for accessing various Storage implementations for Perl in an independent way
44    
45    =head1 SYNOPSIS
46    
47      ... the basic way:
48    
49    
50      ... via inheritance:
51      
52        use Data::Storage;
53        my $proxyObj = new HttpProxy;
54        $proxyObj->{url} = $url;
55        $proxyObj->{payload} = $content;
56        $self->{storage}->insert($proxyObj);
57        
58        use Data::Storage;
59        my $proxyObj = HttpProxy->new(
60          url => $url,
61          payload => $content,
62        );
63        $self->{storage}->insert($proxyObj);
64    
65    
66    =head2 NOTE
67    
68    This module heavily relies on DBI and Tangram, but adds a lot of additional bugs and quirks.
69    Please look at their documentation and this code for additional information.
70    
71    
72    =cut
73    
74    # The POD text continues at the end of the file.
75    
76    
77  package Data::Storage;  package Data::Storage;
78    
79  use strict;  use strict;
80  use warnings;  use warnings;
81    
82  use Data::Storage::Locator;  use Data::Storage::Locator;
83  use Data::Storage::Handler::DBI;  
84  use Data::Storage::Handler::Tangram;  my $TRACELEVEL = 0;
85    
86  # get logger instance  # get logger instance
87  my $logger = Log::Dispatch::Config->instance;  my $logger = Log::Dispatch::Config->instance;
# Line 37  sub new { Line 102  sub new {
102    
103  sub AUTOLOAD {  sub AUTOLOAD {
104        
105      # since this is a core function acting as dispatcher to $self->{STORAGEHANDLE},
106      # some sophisticated handling and filtering is needed to avoid things like
107      #     - Deep recursion on subroutine "Data::Storage::AUTOLOAD"
108      #     - Deep recursion on subroutine "Data::Storage::Handler::Abstract::AUTOLOAD"
109      #     - Deep recursion on anonymous subroutine at [...]
110      # we also might filter log messages caused by logging itself in "advanced logging of AUTOLOAD calls"
111      
112    my $self = shift;    my $self = shift;
113    our $AUTOLOAD;    our $AUTOLOAD;
114        
# Line 46  sub AUTOLOAD { Line 118  sub AUTOLOAD {
118    my $method = $AUTOLOAD;    my $method = $AUTOLOAD;
119    $method =~ s/^.*:://;    $method =~ s/^.*:://;
120    
121    #$logger->debug( __PACKAGE__ . "[$self->{locator}->{type}]" . "->" . $method . "(@_)" . " (AUTOLOAD)" );    # advanced logging of AUTOLOAD calls ...
122      # ... nice but do it only when TRACING (TODO) is enabled
123        if ($TRACELEVEL) {
124          my $logstring = "";
125          $logstring .= __PACKAGE__ . "[$self->{locator}->{type}]" . "->" . $method;
126          #print "count: ", $#_, "\n";
127          #$logstring .= Dumper(@_) if ($#_ != -1);
128          my $tabcount = int( (80 - length($logstring)) / 10 );
129          $logstring .= "\t" x $tabcount . "(AUTOLOAD)";
130          # TODO: only ok if logstring doesn't contain
131          #            e.g. "Data::Storage[Tangram]->insert(SystemEvent=HASH(0x5c0034c))          (AUTOLOAD)"
132          # but that would be way too specific as long as we don't have an abstract handler for this  ;)
133          $logger->debug( $logstring );
134        }
135        
136      # filtering AUTOLOAD calls
137    if ($self->_filter_AUTOLOAD($method)) {    if ($self->_filter_AUTOLOAD($method)) {
138      $self->_accessStorage();      $self->_accessStorage();
139      $self->{STORAGEHANDLE}->$method(@_);      $self->{STORAGEHANDLE}->$method(@_);
# Line 79  sub normalizeArgs { Line 165  sub normalizeArgs {
165  sub _accessStorage {  sub _accessStorage {
166    my $self = shift;    my $self = shift;
167    # TODO: to some tracelevel!    # TODO: to some tracelevel!
168    #$logger->debug( __PACKAGE__ .  "[$self->{type}]" . "->_accessStorage()" );    if ($TRACELEVEL) {
169        $logger->debug( __PACKAGE__ .  "[$self->{locator}->{type}]" . "->_accessStorage()" );
170      }
171    if (!$self->{STORAGEHANDLE}) {    if (!$self->{STORAGEHANDLE}) {
172      $self->_createStorageHandle();      $self->_createStorageHandle();
173    }    }
# Line 96  sub _createStorageHandle { Line 184  sub _createStorageHandle {
184    # propagate args to handler    # propagate args to handler
185    # needs some more thoughts! (not only "dbi" to Tangram, when (in future) db is not more the common case)    # needs some more thoughts! (not only "dbi" to Tangram, when (in future) db is not more the common case)
186    if ($type eq 'DBI') {    if ($type eq 'DBI') {
187        use Data::Storage::Handler::DBI;
188      #my @args = %{$self->{locator}->{dbi}};      #my @args = %{$self->{locator}->{dbi}};
189      my @args = %{$self->{locator}};      my @args = %{$self->{locator}};
190        # create new storage handle
191      $self->{STORAGEHANDLE} = $pkg->new( @args );      $self->{STORAGEHANDLE} = $pkg->new( @args );
192    }    }
193    if ($type eq 'Tangram') {    if ($type eq 'Tangram') {
194        use Data::Storage::Handler::Tangram;
195      #$self->{STORAGEHANDLE} = $pkg->new( dsn => $self->{locator}->{dbi}->{dsn} );      #$self->{STORAGEHANDLE} = $pkg->new( dsn => $self->{locator}->{dbi}->{dsn} );
196      #my @args = %{$self->{locator}->{dbi}};      #my @args = %{$self->{locator}->{dbi}};
197      my @args = %{$self->{locator}};      my @args = %{$self->{locator}};
198        # create new storage handle
199      $self->{STORAGEHANDLE} = $pkg->new( @args );      $self->{STORAGEHANDLE} = $pkg->new( @args );
200    
201      #$self->{STORAGEHANDLE_UNDERLYING} = $self->{STORAGEHANDLE}->getUnderlyingStorage();      #$self->{STORAGEHANDLE_UNDERLYING} = $self->{STORAGEHANDLE}->getUnderlyingStorage();
202      #$self->{STORAGEHANDLE_UNDERLYING}->_configureCOREHANDLE();      #$self->{STORAGEHANDLE_UNDERLYING}->_configureCOREHANDLE();
203    }    }
# Line 116  sub addLogDispatchHandler { Line 209  sub addLogDispatchHandler {
209        my $self = shift;        my $self = shift;
210        my $name = shift;        my $name = shift;
211        my $package = shift;        my $package = shift;
212        my $logger = shift;        my $logger1 = shift;
213        my $objectCreator = shift;        my $objectCreator = shift;
214                
215        #$logger->add( Log::Dispatch::Tangram->new( name => $name,        #$logger->add( Log::Dispatch::Tangram->new( name => $name,
# Line 143  sub removeLogDispatchHandler { Line 236  sub removeLogDispatchHandler {
236    
237        my $self = shift;        my $self = shift;
238        my $name = shift;        my $name = shift;
239        my $logger = shift;        #my $logger = shift;
240    
241        $logger->remove($name);        $logger->remove($name);
242    
# Line 167  sub testDsn { Line 260  sub testDsn {
260      $dbh->disconnect();      $dbh->disconnect();
261      return 1;      return 1;
262    } else {    } else {
263      $logger->error( __PACKAGE__ .  "[$self->{locator}->{type}]" . "->testDsn(): " . "DBI-error: " . DBI::errstr );      $logger->error( __PACKAGE__ .  "[$self->{locator}->{type}]" . "->testDsn(): " . "DBI-error: " . $DBI::errstr );
264    }    }
265  }  }
266    
 1;  
267    sub createDb {
268      my $self = shift;
269      my $dsn = $self->{locator}->{dbi}->{dsn};
270    
271      $logger->debug( __PACKAGE__ .  "->createDb( dsn $dsn )" );
272    
273      $dsn =~ s/database=(.+?);//;
274      my $database_name = $1;
275    
276      my $ok;
277      
278      if ( my $dbh = DBI->connect($dsn, '', '', {
279                                                          PrintError => 0,
280                                                          } ) ) {
281        if ($database_name) {
282          if ($dbh->do("CREATE DATABASE $database_name;")) {
283            $ok = 1;
284          }
285        }
286        $dbh->disconnect();
287      }
288      
289      return $ok;
290      
291    }
292    
293    sub dropDb {
294      my $self = shift;
295      my $dsn = $self->{locator}->{dbi}->{dsn};
296    
297      $logger->debug( __PACKAGE__ .  "->dropDb( dsn $dsn )" );
298    
299      $dsn =~ s/database=(.+?);//;
300      my $database_name = $1;
301    
302      my $ok;
303      
304      if ( my $dbh = DBI->connect($dsn, '', '', {
305                                                          PrintError => 0,
306                                                          } ) ) {
307        if ($database_name) {
308          if ($dbh->do("DROP DATABASE $database_name;")) {
309            $ok = 1;
310          }
311        }
312        $dbh->disconnect();
313      }
314      
315      return $ok;
316    }
317    
318    sub isConnected {
319      my $self = shift;
320      return 1 if $self->{STORAGEHANDLE};
321    }
322    
323    1;
324    __END__
325    
326    
327    =head1 DESCRIPTION
328    
329    Data::Storage is module for a accessing various "data structures" stored inside
330    various "data containers". It sits on top of DBI and/or Tangram.
331    
332    
333    =head1 AUTHORS / COPYRIGHT
334    
335    The Data::Storage module is Copyright (c) 2002 Andreas Motl.
336    All rights reserved.
337    
338    You may distribute it under the terms of either the GNU General Public
339    License or the Artistic License, as specified in the Perl README file.
340    
341    
342    =head1 ACKNOWLEDGEMENTS
343    
344    Larry Wall and the C<perl5-porters> for Perl,
345    Tim Bunce for DBI, Jean-Louis Leroy for Tangram and Set::Object,
346    Sam Vilain for Class::Tangram.
347    
348    
349    =head1 SUPPORT / WARRANTY
350    
351    Data::Storage is free software. IT COMES WITHOUT WARRANTY OF ANY KIND.
352    
353    
354    =head1 TODO
355    
356    
357    =head2 Handle the following errors/cases:
358    
359    =head3 "DBI-Error [Tangram]: DBD::mysql::st execute failed: Unknown column 't1.requestdump' in 'field list'"
360    
361        ... occours when operating on object-attributes not introduced yet:
362        this should be detected and appended/replaced through:
363        "Schema-Error detected, maybe (just) an inconsistency.
364        Please check if your declaration in schema-module "a" matches structure in database "b" or try to run"
365        db_setup.pl --dbkey=import --action=deploy
366    
367    =head3 Compare schema (structure diff) with database ...
368    
369      ... when issuing "db_setup.pl --dbkey=import --action=deploy"
370      on a database with an already deployed schema, use an additional "--update" then
371      to lift the schema inside the database to the current declared schema.
372      You will have to approve removals and changes on field-level while
373      new objects and new fields are introduced silently without any interaction needed.
374      In future versions there may be additional options to control silent processing of
375      removals and changes.
376      See this CRUD-table applying to the actions occouring on Classes and Class variables when deploying schemas,
377      don't mix this up with CRUD-actions on Objects, these are already handled by (e.g.) Tangram itself.
378      Classes:
379        C create    ->  yes, handled automatically
380        R retrieve  ->  no, not subject of this aspect since it is about deployment only
381        U update    ->  yes, automatically for Class meta-attributes, yes/no for Class variables (look at the rules down here)
382        D delete    ->  yes, just by user-interaction
383      Class variables:
384        C create    ->  yes, handled automatically
385        R retrieve  ->  no, not subject of this aspect since it is about deployment only
386        U update    ->  yes, just by user-interaction; maybe automatically if it can be determined that data wouldn't be lost
387        D delete    ->  yes, just by user-interaction
388      
389      It's all about not to be able to loose data simply while this is in pre-alpha stage.
390      And loosing data by being able to modify and redeploy schemas easily is definitely quite easy.
391      
392      As we can see, creations of Classes and new Class variables is handled
393      automatically and this is believed to be the most common case under normal circumstances.
394    
395    
396    =head2 Introduce some features:
397    
398      - Get this stuff together with UML (Unified Modeling Language) and/or standards from ODMG.
399      - Make it possible to load/save schemas in XMI (XML Metadata Interchange),
400        which seems to be most commonly used today, perhaps handle objects with OIFML.
401        Integrate/bundle this with a web-/html-based UML modeling tool or
402        some other interesting stuff like the "Co-operative UML Editor" from Uni Darmstadt. (web-/java-based)
403      - Enable Round Trip Engineering. Keep code and diagrams in sync. Don't annoy/bother the programmers.
404      - Add some more handlers:
405        - look at DBD::CSV, Text::CSV, XML::CSV, XML::Excel
406      - Add some more locations/locators:
407        - PerlDAV: http://www.webdav.org/perldav/
408      - Move to t3, use InCASE
409    
410    
411    =head3 Links:
412    
413      Specs:
414        UML 1.3 Spec: http://cgi.omg.org/cgi-bin/doc?ad/99-06-08.pdf
415        XMI 1.1 Spec: http://cgi.omg.org/cgi-bin/doc?ad/99-10-02.pdf
416        XMI 2.0 Spec: http://cgi.omg.org/docs/ad/01-06-12.pdf
417        ODMG: http://odmg.org/
418        OIFML: http://odmg.org/library/readingroom/oifml.pdf
419    
420      CASE Tools:
421        Rational Rose (commercial): http://www.rational.com/products/rose/
422        Together (commercial): http://www.oi.com/products/controlcenter/index.jsp
423        InCASE - Tangram-based Universal Object Editor
424        Sybase PowerDesigner: http://www.sybase.com/powerdesigner
425      
426      UML Editors:
427        Fujaba (free, university): http://www.fujaba.de/
428        ArgoUML (free): http://argouml.tigris.org/
429        Poseidon (commercial): http://www.gentleware.com/products/poseidonDE.php3
430        Co-operative UML Editor (research): http://www.darmstadt.gmd.de/concert/activities/internal/umledit.html
431        Metamill (commercial): http://www.metamill.com/
432        Violet (university, research, education): http://www.horstmann.com/violet/
433        PyUt (free): http://pyut.sourceforge.net/
434        (Dia (free): http://www.lysator.liu.se/~alla/dia/)
435        UMLet (free, university): http://www.swt.tuwien.ac.at/umlet/index.html
436        Voodoo (free): http://voodoo.sourceforge.net/
437    
438      UML Tools:
439        http://www.objectsbydesign.com/tools/umltools_byPrice.html
440    
441      Further readings:
442        http://www.google.com/search?q=web+based+uml+editor&hl=en&lr=&ie=UTF-8&oe=UTF-8&start=10&sa=N
443        http://www.fernuni-hagen.de/DVT/Aktuelles/01FHHeidelberg.pdf
444        http://www.enhyper.com/src/documentation/
445        http://cis.cs.tu-berlin.de/Dokumente/Diplomarbeiten/2001/skinner.pdf
446        http://citeseer.nj.nec.com/vilain00diagrammatic.html
447        http://archive.devx.com/uml/articles/Smith01/Smith01-3.asp
448    

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

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