/[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.16 - (hide annotations)
Mon Jan 20 16:52:13 2003 UTC (21 years, 5 months ago) by joko
Branch: MAIN
Changes since 1.15: +54 -8 lines
+ now using 'DesignPattern::Object' to create a new 'Data::Storage::Handler::Xyz' on demand - before we did this in a hand-rolled fashion

1 joko 1.15 ## ------------------------------------------------------------------------
2     ##
3 joko 1.16 ## $Id: Storage.pm,v 1.15 2003/01/19 03:12:59 joko Exp $
4 joko 1.15 ##
5     ## Copyright (c) 2002 Andreas Motl <andreas.motl@ilo.de>
6     ##
7     ## See COPYRIGHT section in pod text below for usage and distribution rights.
8     ##
9     ## ------------------------------------------------------------------------
10     ##
11     ## $Log: Storage.pm,v $
12 joko 1.16 ## Revision 1.15 2003/01/19 03:12:59 joko
13     ## + modified header
14     ## - removed pod-documentation - now in 'Storage.pod'
15     ##
16 joko 1.15 ## Revision 1.14 2002/12/19 16:27:59 joko
17     ## - moved 'sub dropDb' to Data::Storage::Handler::DBI
18     ##
19     ## Revision 1.13 2002/12/17 21:54:12 joko
20     ## + feature when using Tangram:
21     ## + what? each object created should delivered with a globally(!?) unique identifier (GUID) besides the native tangram object id (OID)
22     ## + patched Tangram::Storage (jonen)
23     ## + enhanced Data::Storage::Schema::Tangram (joko)
24     ## + enhanced Data::Storage::Handler::Tangram 'sub getObjectByGuid' (jonen)
25     ## + how?
26     ## + each concrete (non-abstract) class gets injected with an additional field/property called 'guid' - this is done (dynamically) on schema level
27     ## + this property ('guid') gets filled on object creation/insertion from 'sub Tangram::Storage::_insert' using Data::UUID from CPAN
28     ## + (as for now) this property can get accessed by calling 'getObjectByGuid' on the already known storage-handle used throughout the application
29     ##
30     ## Revision 1.12 2002/12/12 02:50:15 joko
31     ## + this now (unfortunately) needs DBI for some helper functions
32     ## + TODO: these have to be refactored to another scope! (soon!)
33     ##
34     ## Revision 1.11 2002/12/11 06:53:19 joko
35     ## + updated pod
36     ##
37     ## Revision 1.10 2002/12/07 03:37:23 joko
38     ## + updated pod
39     ##
40     ## Revision 1.9 2002/12/01 22:15:45 joko
41     ## - sub createDb: moved to handler
42     ##
43     ## Revision 1.8 2002/11/29 04:48:23 joko
44     ## + updated pod
45     ##
46     ## Revision 1.7 2002/11/17 06:07:18 joko
47     ## + creating the handler is easier than proposed first - for now :-)
48     ## + sub testAvailability
49     ##
50     ## Revision 1.6 2002/11/09 01:04:58 joko
51     ## + updated pod
52     ##
53     ## Revision 1.5 2002/10/29 19:24:18 joko
54     ## - reduced logging
55     ## + added some pod
56     ##
57     ## Revision 1.4 2002/10/27 18:35:07 joko
58     ## + added pod
59     ##
60     ## Revision 1.3 2002/10/25 11:40:37 joko
61     ## + enhanced robustness
62     ## + more logging for debug-levels
63     ## + sub dropDb
64     ##
65     ## Revision 1.2 2002/10/17 00:04:29 joko
66     ## + sub createDb
67     ## + sub isConnected
68     ## + bugfixes regarding "deep recursion" stuff
69     ##
70     ## Revision 1.1 2002/10/10 03:43:12 cvsjoko
71     ## + new
72     ## ------------------------------------------------------------------------
73 cvsjoko 1.1
74 joko 1.3
75 joko 1.4 BEGIN {
76 joko 1.15 $Data::Storage::VERSION = 0.03;
77 joko 1.4 }
78    
79 cvsjoko 1.1 package Data::Storage;
80    
81     use strict;
82     use warnings;
83    
84 joko 1.16 use Data::Dumper;
85     # FIXME: wipe out!
86     use DBI;
87    
88 cvsjoko 1.1 use Data::Storage::Locator;
89 joko 1.16 use DesignPattern::Object;
90 cvsjoko 1.1
91 joko 1.12
92 joko 1.6 # TODO: actually implement level (integrate with Log::Dispatch)
93 joko 1.5 my $TRACELEVEL = 0;
94    
95 cvsjoko 1.1 # get logger instance
96     my $logger = Log::Dispatch::Config->instance;
97    
98     sub new {
99     my $invocant = shift;
100     my $class = ref($invocant) || $invocant;
101     #my @args = normalizeArgs(@_);
102 joko 1.7
103 cvsjoko 1.1 my $arg_locator = shift;
104     my $arg_options = shift;
105 joko 1.7
106 joko 1.15 if (!$arg_locator) {
107     $logger->critical( __PACKAGE__ . "->new: No locator passed in!" );
108     return;
109     }
110    
111 cvsjoko 1.1 #my $self = { STORAGEHANDLE => undef, @_ };
112     my $self = { STORAGEHANDLE => undef, locator => $arg_locator, options => $arg_options };
113 joko 1.7 #$logger->debug( __PACKAGE__ . "[$self->{locator}->{type}]" . "->new(@_)" );
114     $logger->debug( __PACKAGE__ . "[$arg_locator->{type}]" . "->new(@_)" );
115 cvsjoko 1.1 return bless $self, $class;
116     }
117    
118     sub AUTOLOAD {
119    
120 joko 1.2 # since this is a core function acting as dispatcher to $self->{STORAGEHANDLE},
121     # some sophisticated handling and filtering is needed to avoid things like
122     # - Deep recursion on subroutine "Data::Storage::AUTOLOAD"
123     # - Deep recursion on subroutine "Data::Storage::Handler::Abstract::AUTOLOAD"
124     # - Deep recursion on anonymous subroutine at [...]
125 joko 1.8 # we also might filter log messages caused by logging to itself in "advanced logging of AUTOLOAD calls"
126 joko 1.2
127 cvsjoko 1.1 my $self = shift;
128     our $AUTOLOAD;
129    
130     # ->DESTROY would - if not declared - trigger an AUTOLOAD also
131     return if $AUTOLOAD =~ m/::DESTROY$/;
132    
133     my $method = $AUTOLOAD;
134     $method =~ s/^.*:://;
135    
136 joko 1.5 # advanced logging of AUTOLOAD calls ...
137     # ... nice but do it only when TRACING (TODO) is enabled
138     my $logstring = "";
139     $logstring .= __PACKAGE__ . "[$self->{locator}->{type}]" . "->" . $method;
140     #print "count: ", $#_, "\n";
141     #$logstring .= Dumper(@_) if ($#_ != -1);
142     my $tabcount = int( (80 - length($logstring)) / 10 );
143     $logstring .= "\t" x $tabcount . "(AUTOLOAD)";
144     # TODO: only ok if logstring doesn't contain
145     # e.g. "Data::Storage[Tangram]->insert(SystemEvent=HASH(0x5c0034c)) (AUTOLOAD)"
146 joko 1.8 # but that would be _way_ too specific as long as we don't have an abstract handler for this ;)
147 joko 1.16 if ($TRACELEVEL) {
148 joko 1.5 $logger->debug( $logstring );
149 joko 1.7 #print join('; ', @_);
150 joko 1.5 }
151    
152 joko 1.8 # filtering AUTOLOAD calls and first-time-touch of the actual storage impl
153 cvsjoko 1.1 if ($self->_filter_AUTOLOAD($method)) {
154     $self->_accessStorage();
155 joko 1.16 if ($self->{STORAGEHANDLE}) {
156     return $self->{STORAGEHANDLE}->$method(@_);
157     } else {
158     $logger->critical( __PACKAGE__ . "->AUTOLOAD: ERROR: " . $logstring );
159     return;
160     }
161 cvsjoko 1.1 }
162    
163     }
164    
165     sub _filter_AUTOLOAD {
166     my $self = shift;
167     my $method = shift;
168     if ($self->{options}->{protected}) {
169     if ($method eq 'disconnect') {
170     return;
171     }
172     }
173     return 1;
174     }
175    
176    
177     sub normalizeArgs {
178     my %args = @_;
179     if (!$args{dsn} && $args{meta}{dsn}) {
180     $args{dsn} = $args{meta}{dsn};
181     }
182     my @result = %args;
183     return @result;
184     }
185    
186     sub _accessStorage {
187     my $self = shift;
188     # TODO: to some tracelevel!
189 joko 1.5 if ($TRACELEVEL) {
190     $logger->debug( __PACKAGE__ . "[$self->{locator}->{type}]" . "->_accessStorage()" );
191     }
192 cvsjoko 1.1 if (!$self->{STORAGEHANDLE}) {
193 joko 1.16 return $self->_createStorageHandle();
194     }
195     }
196    
197     sub _createStorageHandle1 {
198     my $self = shift;
199     my $type = $self->{locator}->{type};
200     $logger->debug( __PACKAGE__ . "[$type]" . "->_createStorageHandle()" );
201    
202     my $pkg = "Data::Storage::Handler::" . $type . "";
203    
204     # try to load perl module at runtime
205     my $evalstr = "use $pkg;";
206     eval($evalstr);
207     if ($@) {
208     $logger->error( __PACKAGE__ . "[$type]" . "->_createStorageHandle(): $@" );
209     return;
210 cvsjoko 1.1 }
211 joko 1.16
212     # build up some additional arguments to pass on
213     #my @args = %{$self->{locator}};
214     my @args = ();
215    
216     # - create new storage handle object
217     # - propagate arguments to handler
218     # - pass locator by reference to be able to store status- or meta-information in it
219     $self->{STORAGEHANDLE} = $pkg->new( locator => $self->{locator}, @args );
220    
221 cvsjoko 1.1 }
222    
223     sub _createStorageHandle {
224     my $self = shift;
225     my $type = $self->{locator}->{type};
226     $logger->debug( __PACKAGE__ . "[$type]" . "->_createStorageHandle()" );
227    
228 joko 1.16 #print Dumper($self);
229     #exit;
230    
231 cvsjoko 1.1 my $pkg = "Data::Storage::Handler::" . $type . "";
232    
233 joko 1.7 # try to load perl module at runtime
234 joko 1.16 =pod
235 joko 1.7 my $evalstr = "use $pkg;";
236     eval($evalstr);
237     if ($@) {
238     $logger->error( __PACKAGE__ . "[$type]" . "->_createStorageHandle(): $@" );
239     return;
240 cvsjoko 1.1 }
241 joko 1.7
242     # build up some additional arguments to pass on
243     #my @args = %{$self->{locator}};
244     my @args = ();
245    
246 joko 1.8 # - create new storage handle object
247     # - propagate arguments to handler
248     # - pass locator by reference to be able to store status- or meta-information in it
249 joko 1.7 $self->{STORAGEHANDLE} = $pkg->new( locator => $self->{locator}, @args );
250 joko 1.16 =cut
251    
252     $self->{STORAGEHANDLE} = DesignPattern::Object->fromPackage( $pkg, locator => $self->{locator} );
253     return 1;
254 joko 1.3
255 cvsjoko 1.1 }
256    
257     sub addLogDispatchHandler {
258    
259     my $self = shift;
260     my $name = shift;
261     my $package = shift;
262 joko 1.3 my $logger1 = shift;
263 cvsjoko 1.1 my $objectCreator = shift;
264    
265     #$logger->add( Log::Dispatch::Tangram->new( name => $name,
266     $logger->add( $package->new( name => $name,
267     #min_level => 'debug',
268     min_level => 'info',
269     storage => $self,
270     objectCreator => $objectCreator,
271     fields => {
272     message => 'usermsg',
273     timestamp => 'stamp',
274     level => 'level',
275     name => 'code',
276     },
277     filter_patterns => [ '->insert\(SystemEvent=' ],
278     #filter_patterns => [ 'SystemEvent' ],
279    
280     #format => '[%d] [%p] %m%n',
281     ) );
282    
283     }
284    
285     sub removeLogDispatchHandler {
286 joko 1.8 my $self = shift;
287     my $name = shift;
288     #my $logger = shift;
289     $logger->remove($name);
290 cvsjoko 1.1 }
291    
292 joko 1.16 =pod
293 cvsjoko 1.1 sub getDbName {
294     my $self = shift;
295     my $dsn = $self->{locator}->{dbi}->{dsn};
296     $dsn =~ m/database=(.+?);/;
297     my $database_name = $1;
298     return $database_name;
299     }
300    
301 joko 1.12 sub testAvailability {
302     my $self = shift;
303     my $status = $self->testDsn();
304     $self->{locator}->{status}->{available} = $status;
305     return $status;
306     }
307    
308     sub isConnected {
309     my $self = shift;
310     # TODO: REVIEW!
311     return 1 if $self->{STORAGEHANDLE};
312     }
313    
314 cvsjoko 1.1 sub testDsn {
315     my $self = shift;
316     my $dsn = $self->{locator}->{dbi}->{dsn};
317     my $result;
318     if ( my $dbh = DBI->connect($dsn, '', '', {
319     PrintError => 0,
320     } ) ) {
321 joko 1.9
322     # TODO: REVIEW
323 cvsjoko 1.1 $dbh->disconnect();
324 joko 1.9
325 cvsjoko 1.1 return 1;
326     } else {
327 joko 1.7 $logger->warning( __PACKAGE__ . "[$self->{locator}->{type}]" . "->testDsn(): " . "DBI-error: " . $DBI::errstr );
328 joko 1.2 }
329 cvsjoko 1.1 }
330 joko 1.16 =cut
331 cvsjoko 1.1
332 joko 1.4 1;
333     __END__

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