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

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

Parent Directory Parent Directory | Revision Log Revision Log


Revision 1.6 - (show 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 # $Id: Storage.pm,v 1.5 2002/10/29 19:24:18 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 #################################
8 #
9 # $Log: Storage.pm,v $
10 # Revision 1.5 2002/10/29 19:24:18 joko
11 # - reduced logging
12 # + added some pod
13 #
14 # Revision 1.4 2002/10/27 18:35:07 joko
15 # + added pod
16 #
17 # Revision 1.3 2002/10/25 11:40:37 joko
18 # + enhanced robustness
19 # + more logging for debug-levels
20 # + sub dropDb
21 #
22 # Revision 1.2 2002/10/17 00:04:29 joko
23 # + sub createDb
24 # + sub isConnected
25 # + bugfixes regarding "deep recursion" stuff
26 #
27 # Revision 1.1 2002/10/10 03:43:12 cvsjoko
28 # + new
29 #
30 #################################
31
32 # 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 BEGIN {
37 $Data::Storage::VERSION = 0.01;
38 }
39
40
41 =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 Please look at their documentation and/or this code for additional information.
70
71
72 =head1 REQUIREMENTS
73
74 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
81 =cut
82
83 # The POD text continues at the end of the file.
84
85
86 package Data::Storage;
87
88 use strict;
89 use warnings;
90
91 use Data::Storage::Locator;
92
93 # TODO: actually implement level (integrate with Log::Dispatch)
94 my $TRACELEVEL = 0;
95
96 # 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 # 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 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 # 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 # filtering AUTOLOAD calls
147 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 if ($TRACELEVEL) {
179 $logger->debug( __PACKAGE__ . "[$self->{locator}->{type}]" . "->_accessStorage()" );
180 }
181 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 use Data::Storage::Handler::DBI;
198 #my @args = %{$self->{locator}->{dbi}};
199 my @args = %{$self->{locator}};
200 # create new storage handle
201 $self->{STORAGEHANDLE} = $pkg->new( @args );
202 }
203 if ($type eq 'Tangram') {
204 use Data::Storage::Handler::Tangram;
205 #$self->{STORAGEHANDLE} = $pkg->new( dsn => $self->{locator}->{dbi}->{dsn} );
206 #my @args = %{$self->{locator}->{dbi}};
207 my @args = %{$self->{locator}};
208 # create new storage handle
209 $self->{STORAGEHANDLE} = $pkg->new( @args );
210
211 #$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 my $logger1 = shift;
223 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 #my $logger = shift;
250
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 $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
281 $logger->debug( __PACKAGE__ . "->createDb( dsn $dsn )" );
282
283 $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 }
298
299 return $ok;
300
301 }
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 }
327
328 sub isConnected {
329 my $self = shift;
330 return 1 if $self->{STORAGEHANDLE};
331 }
332
333 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 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
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
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
404
405 =head2 Introduce some features:
406
407 - 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
419
420 =head3 Links:
421
422 Specs:
423 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 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 Umbrello UML Modeller: http://uml.sourceforge.net/
447
448 UML Tools:
449 http://www.objectsbydesign.com/tools/umltools_byPrice.html
450
451 Further readings:
452 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