/[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.4 - (hide annotations)
Sun Oct 27 18:35:07 2002 UTC (21 years, 8 months ago) by joko
Branch: MAIN
Changes since 1.3: +148 -4 lines
+ added pod

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

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