/[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.5 - (hide annotations)
Tue Oct 29 19:24:18 2002 UTC (21 years, 7 months ago) by joko
Branch: MAIN
Changes since 1.4: +65 -25 lines
- reduced logging
+ added some pod

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

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