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

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

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