/[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.6 by joko, Sat Nov 9 01:04:58 2002 UTC revision 1.10 by joko, Sat Dec 7 03:37:23 2002 UTC
# Line 4  Line 4 
4  #  #
5  # See COPYRIGHT section in pod text below for usage and distribution rights.  # See COPYRIGHT section in pod text below for usage and distribution rights.
6  #  #
7  #################################  ############################################
8  #  #
9  #  $Log$  #  $Log$
10    #  Revision 1.10  2002/12/07 03:37:23  joko
11    #  + updated pod
12    #
13    #  Revision 1.9  2002/12/01 22:15:45  joko
14    #  - sub createDb: moved to handler
15    #
16    #  Revision 1.8  2002/11/29 04:48:23  joko
17    #  + updated pod
18    #
19    #  Revision 1.7  2002/11/17 06:07:18  joko
20    #  + creating the handler is easier than proposed first - for now :-)
21    #  + sub testAvailability
22    #
23  #  Revision 1.6  2002/11/09 01:04:58  joko  #  Revision 1.6  2002/11/09 01:04:58  joko
24  #  + updated pod  #  + updated pod
25  #  #
# Line 30  Line 43 
43  #  Revision 1.1  2002/10/10 03:43:12  cvsjoko  #  Revision 1.1  2002/10/10 03:43:12  cvsjoko
44  #  + new  #  + new
45  #  #
46  #################################  ############################################
47    
 # aim_V1: should encapsulate Tangram, DBI, DBD::CSV and LWP:: to access them in an unordinary way ;)  
 # aim_V2: introduce a generic layered structure, refactor *SUBLAYER*-stuff, make (e.g.) this possible:  
 #               - Perl Data::Storage[DBD::CSV]  ->  Perl LWP::  ->  Internet HTTP/FTP/*  ->  Host Daemon  ->  csv-file  
48    
49  BEGIN {  BEGIN {
50  $Data::Storage::VERSION = 0.01;    $Data::Storage::VERSION = 0.02;
51  }  }
52    
53    
# Line 45  $Data::Storage::VERSION = 0.01; Line 55  $Data::Storage::VERSION = 0.01;
55    
56  Data::Storage - Interface for accessing various Storage implementations for Perl in an independent way  Data::Storage - Interface for accessing various Storage implementations for Perl in an independent way
57    
58    
59    =head1 AIMS
60    
61      - should encapsulate Tangram, DBI, DBD::CSV and LWP:: to access them in an unordinary (more convenient) way ;)
62      - introduce a generic layered structure, refactor *SUBLAYER*-stuff, make (e.g.) this possible:
63        Perl Data::Storage[DBD::CSV]  ->  Perl LWP::  ->  Internet HTTP/FTP/*  ->  Host Daemon  ->  csv-file
64      - provide generic synchronization mechanisms across arbitrary/multiple storages based on ident/checksum
65        maybe it's possible to have schema-, structural- and semantical modifications synchronized???
66    
67    
68  =head1 SYNOPSIS  =head1 SYNOPSIS
69    
70    ... the basic way:  =head2 BASIC ACCESS
71    
72    =head2 ADVANCED ACCESS
73    
74    ... via inheritance:    ... via inheritance:
75        
# Line 66  Data::Storage - Interface for accessing Line 87  Data::Storage - Interface for accessing
87      $self->{storage}->insert($proxyObj);      $self->{storage}->insert($proxyObj);
88    
89    
90    =head2 SYNCHRONIZATION
91    
92      my $nodemapping = {
93        'LangText' => 'langtexts.csv',
94        'Currency' => 'currencies.csv',
95        'Country'  => 'countries.csv',
96      };
97    
98      my $propmapping = {
99        'LangText' => [
100          [ 'source:lcountrykey'  =>  'target:country' ],
101          [ 'source:lkey'         =>  'target:key' ],
102          [ 'source:lvalue'       =>  'target:text' ],
103        ],
104        'Currency' => [
105          [ 'source:ckey'         =>  'target:key' ],
106          [ 'source:cname'        =>  'target:text' ],
107        ],
108        'Country' => [
109          [ 'source:ckey'         =>  'target:key' ],
110          [ 'source:cname'        =>  'target:text' ],
111        ],
112      };
113    
114      sub syncResource {
115    
116        my $self = shift;
117        my $node_source = shift;
118        my $mode = shift;
119        my $opts = shift;
120        
121        $mode ||= '';
122        $opts->{erase} ||= 0;
123        
124        $logger->info( __PACKAGE__ . "->syncResource( node_source $node_source mode $mode erase $opts->{erase} )");
125      
126        # resolve metadata for syncing requested resource
127        my $node_target = $nodemapping->{$node_source};
128        my $mapping = $propmapping->{$node_source};
129        
130        if (!$node_target || !$mapping) {
131          # loggger.... "no target, sorry!"
132          print "error while resolving resource metadata", "\n";
133          return;
134        }
135        
136        if ($opts->{erase}) {
137          $self->_erase_all($node_source);
138        }
139      
140        # create new sync object
141        my $sync = Data::Transfer::Sync->new(
142          storages => {
143            L => $self->{bizWorks}->{backend},
144            R => $self->{bizWorks}->{resources},
145          },
146          id_authorities        =>  [qw( L ) ],
147          checksum_authorities  =>  [qw( L ) ],
148          write_protected       =>  [qw( R ) ],
149          verbose               =>  1,
150        );
151        
152        # sync
153        # todo: filter!?
154        $sync->syncNodes( {
155          direction       =>  $mode,                 # | +PUSH | +PULL | -FULL | +IMPORT | -EXPORT
156          method          =>  'checksum',            # | -timestamp | -manual
157          source          =>  "L:$node_source",
158          source_ident    =>  'storage_method:id',
159          source_exclude  =>  [qw( id cs )],
160          target          =>  "R:$node_target",
161          target_ident    =>  'property:oid',
162          mapping         =>  $mapping,
163        } );
164    
165      }
166    
167    
168  =head2 NOTE  =head2 NOTE
169    
170  This module heavily relies on DBI and Tangram, but adds a lot of additional bugs and quirks.  This module heavily relies on DBI and Tangram, but adds a lot of additional bugs and quirks.
# Line 74  Please look at their documentation and/o Line 173  Please look at their documentation and/o
173    
174  =head1 REQUIREMENTS  =head1 REQUIREMENTS
175    
176  For full functionality:    For full functionality:
177    DBI              from CPAN      DBI              from CPAN
178    Tangram          from CPAN      DBD::mysql       from CPAN
179    Class::Tangram   from CPAN      Tangram 2.04     from CPAN         (hmmm, 2.04 won't do in some cases)
180    MySQL::Diff      from http://adamspiers.org/computing/mysqldiff/      Tangram 2.05     from http://...   (2.05 seems okay but there are also additional patches from our side)
181    ... and all their dependencies      Class::Tangram   from CPAN
182        DBD::CSV         from CPAN
183        MySQL::Diff      from http://adamspiers.org/computing/mysqldiff/
184        ... and all their dependencies
185    
186  =cut  =cut
187    
# Line 92  use strict; Line 194  use strict;
194  use warnings;  use warnings;
195    
196  use Data::Storage::Locator;  use Data::Storage::Locator;
197    use Data::Dumper;
198    
199  # TODO: actually implement level (integrate with Log::Dispatch)  # TODO: actually implement level (integrate with Log::Dispatch)
200  my $TRACELEVEL = 0;  my $TRACELEVEL = 0;
# Line 103  sub new { Line 206  sub new {
206    my $invocant = shift;    my $invocant = shift;
207    my $class = ref($invocant) || $invocant;    my $class = ref($invocant) || $invocant;
208    #my @args = normalizeArgs(@_);    #my @args = normalizeArgs(@_);
209      
210    my $arg_locator = shift;    my $arg_locator = shift;
211    my $arg_options = shift;    my $arg_options = shift;
212      
213    #my $self = { STORAGEHANDLE => undef, @_ };    #my $self = { STORAGEHANDLE => undef, @_ };
214    my $self = { STORAGEHANDLE => undef, locator => $arg_locator, options => $arg_options };    my $self = { STORAGEHANDLE => undef, locator => $arg_locator, options => $arg_options };
215    $logger->debug( __PACKAGE__ . "[$self->{locator}->{type}]" . "->new(@_)" );    #$logger->debug( __PACKAGE__ . "[$self->{locator}->{type}]" . "->new(@_)" );
216      $logger->debug( __PACKAGE__ . "[$arg_locator->{type}]" . "->new(@_)" );
217    return bless $self, $class;    return bless $self, $class;
218  }  }
219    
# Line 120  sub AUTOLOAD { Line 224  sub AUTOLOAD {
224    #     - Deep recursion on subroutine "Data::Storage::AUTOLOAD"    #     - Deep recursion on subroutine "Data::Storage::AUTOLOAD"
225    #     - Deep recursion on subroutine "Data::Storage::Handler::Abstract::AUTOLOAD"    #     - Deep recursion on subroutine "Data::Storage::Handler::Abstract::AUTOLOAD"
226    #     - Deep recursion on anonymous subroutine at [...]    #     - Deep recursion on anonymous subroutine at [...]
227    # we also might filter log messages caused by logging itself in "advanced logging of AUTOLOAD calls"    # we also might filter log messages caused by logging to itself in "advanced logging of AUTOLOAD calls"
228        
229    my $self = shift;    my $self = shift;
230    our $AUTOLOAD;    our $AUTOLOAD;
# Line 142  sub AUTOLOAD { Line 246  sub AUTOLOAD {
246        $logstring .= "\t" x $tabcount . "(AUTOLOAD)";        $logstring .= "\t" x $tabcount . "(AUTOLOAD)";
247        # TODO: only ok if logstring doesn't contain        # TODO: only ok if logstring doesn't contain
248        #            e.g. "Data::Storage[Tangram]->insert(SystemEvent=HASH(0x5c0034c))          (AUTOLOAD)"        #            e.g. "Data::Storage[Tangram]->insert(SystemEvent=HASH(0x5c0034c))          (AUTOLOAD)"
249        # but that would be way too specific as long as we don't have an abstract handler for this  ;)        # but that would be _way_ too specific as long as we don't have an abstract handler for this  ;)
250        $logger->debug( $logstring );        $logger->debug( $logstring );
251          #print join('; ', @_);
252      }      }
253            
254    # filtering AUTOLOAD calls    # filtering AUTOLOAD calls and first-time-touch of the actual storage impl
255    if ($self->_filter_AUTOLOAD($method)) {    if ($self->_filter_AUTOLOAD($method)) {
256        #print "_accessStorage\n";
257      $self->_accessStorage();      $self->_accessStorage();
258      $self->{STORAGEHANDLE}->$method(@_);      $self->{STORAGEHANDLE}->$method(@_);
259    }    }
# Line 188  sub _accessStorage { Line 294  sub _accessStorage {
294    
295  sub _createStorageHandle {  sub _createStorageHandle {
296    my $self = shift;    my $self = shift;
   
297    my $type = $self->{locator}->{type};    my $type = $self->{locator}->{type};
298    $logger->debug( __PACKAGE__ .  "[$type]" . "->_createStorageHandle()" );    $logger->debug( __PACKAGE__ .  "[$type]" . "->_createStorageHandle()" );
299    
300    my $pkg = "Data::Storage::Handler::" . $type . "";    my $pkg = "Data::Storage::Handler::" . $type . "";
301        
302    # propagate args to handler    # try to load perl module at runtime
303    # needs some more thoughts! (not only "dbi" to Tangram, when (in future) db is not more the common case)    my $evalstr = "use $pkg;";
304    if ($type eq 'DBI') {    eval($evalstr);
305      use Data::Storage::Handler::DBI;    if ($@) {
306      #my @args = %{$self->{locator}->{dbi}};      $logger->error( __PACKAGE__ .  "[$type]" . "->_createStorageHandle(): $@" );
307      my @args = %{$self->{locator}};      return;
     # create new storage handle  
     $self->{STORAGEHANDLE} = $pkg->new( @args );  
   }  
   if ($type eq 'Tangram') {  
     use Data::Storage::Handler::Tangram;  
     #$self->{STORAGEHANDLE} = $pkg->new( dsn => $self->{locator}->{dbi}->{dsn} );  
     #my @args = %{$self->{locator}->{dbi}};  
     my @args = %{$self->{locator}};  
     # create new storage handle  
     $self->{STORAGEHANDLE} = $pkg->new( @args );  
   
     #$self->{STORAGEHANDLE_UNDERLYING} = $self->{STORAGEHANDLE}->getUnderlyingStorage();  
     #$self->{STORAGEHANDLE_UNDERLYING}->_configureCOREHANDLE();  
308    }    }
309        
310      # build up some additional arguments to pass on
311      #my @args = %{$self->{locator}};
312      my @args = ();
313    
314      # - create new storage handle object
315      # - propagate arguments to handler
316      # - pass locator by reference to be able to store status- or meta-information in it
317      $self->{STORAGEHANDLE} = $pkg->new( locator => $self->{locator}, @args );
318    
319  }  }
320    
321  sub addLogDispatchHandler {  sub addLogDispatchHandler {
# Line 246  sub addLogDispatchHandler { Line 347  sub addLogDispatchHandler {
347  }  }
348    
349  sub removeLogDispatchHandler {  sub removeLogDispatchHandler {
350      my $self = shift;
351        my $self = shift;    my $name = shift;
352        my $name = shift;    #my $logger = shift;
353        #my $logger = shift;    $logger->remove($name);
   
       $logger->remove($name);  
   
354  }  }
355    
356  sub getDbName {  sub getDbName {
# Line 270  sub testDsn { Line 368  sub testDsn {
368    if ( my $dbh = DBI->connect($dsn, '', '', {    if ( my $dbh = DBI->connect($dsn, '', '', {
369                                                        PrintError => 0,                                                        PrintError => 0,
370                                                        } ) ) {                                                        } ) ) {
371        
372        # TODO: REVIEW
373      $dbh->disconnect();      $dbh->disconnect();
374        
375      return 1;      return 1;
376    } else {    } else {
377      $logger->error( __PACKAGE__ .  "[$self->{locator}->{type}]" . "->testDsn(): " . "DBI-error: " . $DBI::errstr );      $logger->warning( __PACKAGE__ .  "[$self->{locator}->{type}]" . "->testDsn(): " . "DBI-error: " . $DBI::errstr );
378    }    }
379  }  }
380    
381  sub createDb {  sub testAvailability {
382    my $self = shift;    my $self = shift;
383    my $dsn = $self->{locator}->{dbi}->{dsn};    my $status = $self->testDsn();
384      $self->{locator}->{status}->{available} = $status;
385    $logger->debug( __PACKAGE__ .  "->createDb( dsn $dsn )" );    return $status;
   
   $dsn =~ s/database=(.+?);//;  
   my $database_name = $1;  
   
   my $ok;  
     
   if ( my $dbh = DBI->connect($dsn, '', '', {  
                                                       PrintError => 0,  
                                                       } ) ) {  
     if ($database_name) {  
       if ($dbh->do("CREATE DATABASE $database_name;")) {  
         $ok = 1;  
       }  
     }  
     $dbh->disconnect();  
   }  
     
   return $ok;  
     
386  }  }
387    
388    
389  sub dropDb {  sub dropDb {
390    my $self = shift;    my $self = shift;
391    my $dsn = $self->{locator}->{dbi}->{dsn};    my $dsn = $self->{locator}->{dbi}->{dsn};
# Line 322  sub dropDb { Line 405  sub dropDb {
405          $ok = 1;          $ok = 1;
406        }        }
407      }      }
408    
409      $dbh->disconnect();      $dbh->disconnect();
410    
411    }    }
412        
413    return $ok;    return $ok;
# Line 339  __END__ Line 424  __END__
424    
425  =head1 DESCRIPTION  =head1 DESCRIPTION
426    
427  Data::Storage is module for a accessing various "data structures" stored inside  Data::Storage is a module for accessing various "data structures" stored inside
428  various "data containers". It sits on top of DBI and/or Tangram.  various "data containers". It sits on top of DBI and/or Tangram.
429    
430    
# Line 355  License or the Artistic License, as spec Line 440  License or the Artistic License, as spec
440  =head1 ACKNOWLEDGEMENTS  =head1 ACKNOWLEDGEMENTS
441    
442  Larry Wall for Perl, Tim Bunce for DBI, Jean-Louis Leroy for Tangram and Set::Object,  Larry Wall for Perl, Tim Bunce for DBI, Jean-Louis Leroy for Tangram and Set::Object,
443  Sam Vilain for Class::Tangram, Adam Spiers for MySQL::Diff and all contributors.  Sam Vilain for Class::Tangram, Jochen Wiedmann and Jeff Zucker for DBD::CSV and related,
444    Adam Spiers for MySQL::Diff and all contributors.
445    
446    
447  =head1 SUPPORT / WARRANTY  =head1 SUPPORT / WARRANTY
# Line 366  Data::Storage is free software. IT COMES Line 452  Data::Storage is free software. IT COMES
452  =head1 TODO  =head1 TODO
453    
454    
455  =head2 Handle the following errors/cases:  =head2 BUGS
456    
457  =head3 "DBI-Error [Tangram]: DBD::mysql::st execute failed: Unknown column 't1.requestdump' in 'field list'"  "DBI-Error [Tangram]: DBD::mysql::st execute failed: Unknown column 't1.requestdump' in 'field list'"
458    
459      ... occours when operating on object-attributes not introduced yet:    ... occours when operating on object-attributes not introduced yet:
460      this should be detected and appended/replaced through:    this should be detected and appended/replaced through:
461      "Schema-Error detected, maybe (just) an inconsistency.    "Schema-Error detected, maybe (just) an inconsistency.
462      Please check if your declaration in schema-module "a" matches structure in database "b" or try to run"    Please check if your declaration in schema-module "a" matches structure in database "b" or try to run"
463      db_setup.pl --dbkey=import --action=deploy    db_setup.pl --dbkey=import --action=deploy
464    
465  =head3 Compare schema (structure diff) with database ...  
466    Compare schema (structure diff) with database ...
467    
468    ... when issuing "db_setup.pl --dbkey=import --action=deploy"    ... when issuing "db_setup.pl --dbkey=import --action=deploy"
469    on a database with an already deployed schema, use an additional "--update" then    on a database with an already deployed schema, use an additional "--update" then
# Line 405  Data::Storage is free software. IT COMES Line 492  Data::Storage is free software. IT COMES
492    automatically and this is believed to be the most common case under normal circumstances.    automatically and this is believed to be the most common case under normal circumstances.
493    
494    
495  =head2 Introduce some features:  =head2 FEATURES
496    
497    - Get this stuff together with UML (Unified Modeling Language) and/or standards from ODMG.    - Get this stuff together with UML (Unified Modeling Language) and/or standards from ODMG.
498    - Make it possible to load/save schemas in XMI (XML Metadata Interchange),    - Make it possible to load/save schemas in XMI (XML Metadata Interchange),
# Line 413  Data::Storage is free software. IT COMES Line 500  Data::Storage is free software. IT COMES
500      Integrate/bundle this with a web-/html-based UML modeling tool or      Integrate/bundle this with a web-/html-based UML modeling tool or
501      some other interesting stuff like the "Co-operative UML Editor" from Uni Darmstadt. (web-/java-based)      some other interesting stuff like the "Co-operative UML Editor" from Uni Darmstadt. (web-/java-based)
502    - Enable Round Trip Engineering. Keep code and diagrams in sync. Don't annoy/bother the programmers.    - Enable Round Trip Engineering. Keep code and diagrams in sync. Don't annoy/bother the programmers.
503    - Add some more handlers:    - Add support for some more handlers/locators to be able to
504      - look at DBD::CSV, Text::CSV, XML::CSV, XML::Excel       access the following standards/protocols/interfaces/programs/apis transparently:
505    - Add some more locations/locators:      +  DBD::CSV (via Data::Storage::Handler::DBI)
506      - PerlDAV: http://www.webdav.org/perldav/     (-) Text::CSV, XML::CSV, XML::Excel
507    - Move to t3, use InCASE      -  MAPI
508        -  LDAP
509        -  DAV (look at PerlDAV: http://www.webdav.org/perldav/)
510        -  Mbox (use formail for seperating/splitting entries/nodes)
511        -  Cyrus (cyrdeliver - what about cyrretrieve (export)???)
512        -  use File::DiffTree, use File::Compare
513        -  Hibernate
514        -  "Win32::UserAccountDb"
515        -  "*nix::UserAccountDb"
516        -  .wab - files (Windows Address Book)
517        -  .pst - files (Outlook Post Storage?)
518        -  XML (e.g. via XML::Simple?)
519      - Move to t3, look at InCASE
520      - some kind of security layer for methods/objects
521        - acls (stored via tangram/ldap?) for functions, methods and objects (entity- & data!?)
522        - where are the hooks needed then?
523          - is Data::Storage & Co. okay, or do we have to touch the innards of DBI and/or Tangram?
524          - an attempt to start could be:
525             - 'sub getACLByObjectId($id, $context)'
526             - 'sub getACLByMethodname($id, $context)'
527             - 'sub getACLByName($id, $context)'
528                ( would require a kinda registry to look up these very names pointing to arbitrary locations (code, data, ...) )
529    
530    
531    
532  =head3 Links:  =head3 LINKS / REFERENCES
533    
534    Specs:    Specs:
535      UML 1.3 Spec: http://cgi.omg.org/cgi-bin/doc?ad/99-06-08.pdf      UML 1.3 Spec: http://cgi.omg.org/cgi-bin/doc?ad/99-06-08.pdf

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

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