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

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

Parent Directory Parent Directory | Revision Log Revision Log


Revision 1.6 - (hide annotations)
Sat Nov 9 01:04:58 2002 UTC (21 years, 7 months ago) by joko
Branch: MAIN
Changes since 1.5: +19 -5 lines
+ updated pod

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

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