/[cvs]/nfo/perl/libs/Data/Transfer/Sync/API.pm
ViewVC logotype

Annotation of /nfo/perl/libs/Data/Transfer/Sync/API.pm

Parent Directory Parent Directory | Revision Log Revision Log


Revision 1.1 - (hide annotations)
Sun Jan 19 01:23:04 2003 UTC (21 years, 5 months ago) by joko
Branch: MAIN
+ new from Data/Transfer/Sync.pm

1 joko 1.1 ## $Id: Sync.pm,v 1.11 2002/12/23 07:10:59 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     ## $Log: Sync.pm,v $
9     ## ----------------------------------------------------------------------------------------
10    
11    
12     package Data::Transfer::Sync::API;
13    
14     use strict;
15     use warnings;
16    
17     use mixin::with qw( Data::Transfer::Sync );
18    
19    
20     # - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - main
21    
22     use Data::Dumper;
23    
24     use Data::Compare::Struct qw( getDifference isEmpty );
25     use Data::Transform::Deep qw( merge );
26    
27     # get logger instance
28     my $logger = Log::Dispatch::Config->instance;
29    
30     sub _init {
31     my $self = shift;
32     }
33    
34     sub checkOptions {
35     my $self = shift;
36     my $opts = shift;
37    
38     my $result = 1;
39    
40     # check - do we have a target node?
41     if (!$opts->{target_node}) {
42     $logger->warning( __PACKAGE__ . "->checkOptions: Error while resolving resource metadata - no 'target node' could be determined.");
43     $result = 0;
44     }
45    
46     # check - do we have a mapping?
47     if (!$opts->{mapping} && !$opts->{mapping_module}) {
48     $logger->warning( __PACKAGE__ . "->checkOptions: Error while resolving resource metadata - no 'mapping' could be determined.");
49     $result = 0;
50     }
51    
52     return $result;
53    
54     }
55    
56     sub checkOptionsV2 {
57     my $self = shift;
58    
59     #print Dumper($self->{options});
60    
61     my $result = 1;
62    
63     # check - do we have a target node?
64     if (!$self->{options}->{target}->{nodeName}) {
65     $logger->warning( __PACKAGE__ . "->checkOptionsV2: No target given - please check metadata declaration.");
66     $result = 0;
67     }
68    
69     # check - do we have a mapping?
70     if (!$self->{options}->{fieldmap}) {
71     $logger->warning( __PACKAGE__ . "->checkOptionsV2: Error while resolving resource metadata - no 'fieldmap' could be determined.");
72     $result = 0;
73     }
74    
75     # TODO: extend!
76    
77     return $result;
78    
79     }
80    
81    
82     sub prepareOptions {
83    
84     my $self = shift;
85     my $opts = shift;
86    
87     #print Dumper($opts);
88     #exit;
89    
90     $opts->{mode} ||= '';
91     $opts->{erase} ||= 0;
92     $opts->{prepare} ||= 0;
93     #$opts->{import} ||= 0;
94    
95     if (!$opts->{source_node}) {
96     $logger->error( __PACKAGE__ . "->prepareOptions failed: Please specify source-node!");
97     return;
98     }
99    
100     $logger->notice( __PACKAGE__ . "->prepareOptions( source_node $opts->{source_node} mode $opts->{mode} erase $opts->{erase} prepare $opts->{prepare} )");
101    
102     #if (!$opts->{mapping} || !$opts->{mapping_module}) {
103     if (!$opts->{mapping}) {
104     $logger->warning( __PACKAGE__ . "->prepareOptions: No mapping supplied - please check key 'mappings' in global configuration or specify additional argument '--mapping'.");
105     #return;
106     }
107    
108     $opts->{mapping_module} ||= $opts->{mapping};
109     my $evstring = "use $opts->{mapping_module};";
110     eval($evstring);
111     if ($@) {
112     $logger->warning( __PACKAGE__ . "->prepareOptions: error while trying to access mapping - $@");
113     return;
114     }
115    
116     # resolve mapping metadata (returned from sub)
117     my $mapObject = $opts->{mapping_module}->new();
118     #print Dumper($map);
119     my $source_node_name = $opts->{source_node};
120     # check if mapping for certain node is contained in mapping object
121     if (!$mapObject->can($source_node_name)) {
122     $logger->warning( __PACKAGE__ . "->prepareOptions: Can't access mapping for node \"$source_node_name\" - please check $opts->{mapping_module}.");
123     return;
124     }
125     my $map = $mapObject->$source_node_name;
126    
127     #print Dumper($map);
128    
129     # check here if "target" is actually a CODEref - in this case: resolve it - deprecated!!! ???
130     if (ref $map->{target} eq 'CODE') {
131     $map->{target} = $map->{target}->($source_node_name);
132     }
133    
134     # resolve expressions (on nodename-level) here
135     if ($map->{target} =~ m/^(code|expr):(.+?)$/) {
136     my $target_dynamic_type = $1;
137     my $target_dynamic_expression = $2;
138     if (lc $target_dynamic_type eq 'code') {
139     # $map->{target} = $mapObject->$target_dynamic_expression($map);
140     }
141     }
142    
143     # remove asymmetries from $map (patch keys)
144     $map->{source_node} = $map->{source}; delete $map->{source};
145     $map->{target_node} = $map->{target}; delete $map->{target};
146     $map->{mapping} = $map->{details}; delete $map->{details};
147     $map->{direction} = $map->{mode}; delete $map->{mode};
148    
149     # defaults (mostly for backward-compatibility)
150     $map->{source_node} ||= $source_node_name;
151     $map->{source_ident} ||= 'storage_method:id';
152     $map->{target_ident} ||= 'property:oid';
153     $map->{direction} ||= $opts->{mode}; # | PUSH | PULL | FULL
154     $map->{method} ||= 'checksum'; # | timestamp
155     $map->{source_exclude} ||= [qw( cs )];
156    
157     # merge map to opts
158     map { $opts->{$_} = $map->{$_}; } keys %$map;
159    
160     #print Dumper($opts);
161    
162     # TODO: move this to checkOptions...
163    
164     # check - do we have a target?
165     if (!$opts->{target_node}) {
166     $logger->warning( __PACKAGE__ . "->prepareOptions: No target given - please check metadata declaration.");
167     return;
168     }
169    
170    
171     #return $opts;
172     return 1;
173    
174     }
175    
176     sub prepareOptionsV2 {
177    
178     my $self = shift;
179     my $opts = shift;
180    
181     # patch options
182     $opts->{process}->{mode} ||= '';
183     $opts->{process}->{prepare} ||= 0;
184     $opts->{process}->{erase} ||= 0;
185    
186     # pre-check options
187     if (!$self->_preCheckOptions($opts)) {
188     $logger->error( __PACKAGE__ . "->prepareOptionsV2: _preCheckOptions failed.");
189     return;
190     }
191    
192     # inform user about option preparation
193     $logger->notice( __PACKAGE__ . "->prepareOptionsV2( mode='$opts->{process}->{mode}', source->node='$opts->{source}->{nodeName}', target->node='$opts->{target}->{nodeName}', erase='$opts->{process}->{erase}', prepare='$opts->{process}->{prepare}' )");
194    
195     # try to load mapping-metadata-container
196     #my $mapObject = getNewPerlObjectByPkgName($opts->{map}->{moduleName});
197     my $mapObject = DesignPattern::Object->fromPackage($opts->{map}->{moduleName});
198    
199     # try to resolve map from metadata-container
200    
201     # type of the item/node
202     my $source_nodeType = $opts->{source}->{nodeType};
203    
204     # check if mapping for certain node is contained in mapping object
205     if (!$mapObject->can($source_nodeType)) {
206     $logger->warning( __PACKAGE__ . "->prepareOptionsV2: Can't access mapping for source-type=\"$source_nodeType\" - please check \"$opts->{map}->{moduleName}\".");
207     return;
208     }
209    
210    
211     # get map
212     my $map = $mapObject->$source_nodeType;
213     #print Dumper($map);
214    
215     =pod
216     # check here if "target" is actually a CODEref - in this case: resolve it - deprecated!!! ???
217     if (ref $map->{target}->{address} eq 'CODE') {
218     $map->{target}->{address} = $map->{target}->{address}->($source_nodeType);
219     }
220    
221     # resolve expressions (on nodename-level) here
222     if ($map->{target}->{address} =~ m/^(code|expr):(.+?)$/) {
223     my $target_dynamic_type = $1;
224     my $target_dynamic_expression = $2;
225     if (lc $target_dynamic_type eq 'code') {
226     $map->{target} = $mapObject->$target_dynamic_expression($map);
227     }
228     }
229     =cut
230    
231     #map { $opts->{$_} = $map->{$_}; } keys %$map;
232     my $opts_merged = merge( $opts, $map );
233    
234     $self->{options} = $opts_merged;
235     $self->{state}->{options_ready} = 1;
236    
237     return 1;
238    
239     }
240    
241    
242     sub configure {
243     my $self = shift;
244     my @args = @_;
245     if (!isEmpty(\@args)) {
246     my %properties = @_;
247     # merge args to properties
248     map { $self->{$_} = $properties{$_}; } keys %properties;
249     $self->_init();
250     $self->_initV1();
251     } else {
252     #print "no args!", "\n";
253     }
254     #print Dumper($self);
255     $self->{state}->{configured} = 1;
256     return 1;
257     }
258    
259     sub configureV2 {
260     my $self = shift;
261     my @args = @_;
262     if (!isEmpty(\@args)) {
263     my %properties = @_;
264     # merge args to properties
265     #map { $self->{$_} = $properties{$_}; } keys %properties;
266     $self->{options} = merge($self->{options}, \%properties);
267     $self->_init();
268     #$self->_initV1();
269     } else {
270     #print "no args!", "\n";
271     }
272    
273     #print Dumper($self);
274    
275     $self->{state}->{configured} = 1;
276     return 1;
277     }
278    
279    
280     # TODO: some feature to show off the progress of synchronization (cur/max * 100)
281     sub syncNodes {
282    
283     my $self = shift;
284     my $args = shift;
285    
286     if (!$self->{state}->{configured}) {
287     $logger->critical( __PACKAGE__ . "->syncNodes: Synchronization object is not configured/initialized correctly." );
288     return;
289     }
290    
291     # remember arguments through the whole processing
292     $self->{args} = $args;
293    
294     $logger->debug( __PACKAGE__ . "->syncNodes: starting" );
295    
296     # hash to hold and/or fill in metadata required for the processing
297     $self->{meta} = {};
298    
299     # hash to sum up results
300     my $direction_arrow = '';
301    
302     # detect synchronization method to determine which optical symbol (directed arrow) to use
303     if (lc $self->{args}->{direction} eq 'push') {
304     $direction_arrow = '->';
305     } elsif (lc $self->{args}->{direction} eq 'pull') {
306     $direction_arrow = '<-';
307     } elsif (lc $self->{args}->{direction} eq 'full') {
308     $direction_arrow = '<->';
309     } else {
310     }
311    
312     print Dumper($self);
313     #exit;
314    
315     if (!$self->{metadata}->{version} || $self->{metadata}->{version} < 0.2) {
316     $self->_buildMetadataV1();
317     } else {
318     $self->_buildMetadataV1();
319     #$self->_buildMetadataV2();
320     }
321    
322     #print Dumper($self);
323     #print Dumper($self->{meta});
324    
325     $logger->info( __PACKAGE__ . "->syncNodes: source=$self->{meta}->{source}->{dbkey}/$self->{meta}->{source}->{node} $direction_arrow target=$self->{meta}->{target}->{dbkey}/$self->{meta}->{target}->{node}" );
326    
327     $self->_buildFieldmappingV1();
328    
329     #print Dumper($self->{meta});
330    
331     # check partners/nodes: does partner exist / is node available?
332     foreach my $partner (keys %{$self->{meta}}) {
333    
334     # 1. check partners & storages
335     if (!$self->{meta}->{$partner}) {
336     $logger->critical( __PACKAGE__ . "->syncNodes: Could not find partner '$partner' in configuration metadata." );
337     return;
338     }
339    
340     my $dbkey = $self->{meta}->{$partner}->{dbkey};
341    
342     #print Dumper($self->{meta});
343    
344     if (!$self->{meta}->{$partner}->{storage}) {
345     $logger->critical( __PACKAGE__ . "->syncNodes: Could not access storage of partner '$partner' (named '$dbkey'), looks like a configuration-error." );
346     return;
347     }
348    
349     # TODO:
350     # 2. check if partners (and nodes?) are actually available....
351     # eventually pre-check mode of access-attempt (read/write) here to provide an "early-croak" if possible
352    
353     # print Dumper($self->{meta}->{$partner}->{storage}->{locator});
354    
355     my $dbType = $self->{meta}->{$partner}->{storage}->{locator}->{type};
356     #print "dbType: $dbType", "\n";
357    
358     # 3. check nodes
359     next if $dbType eq 'DBI'; # HACK for DBD::CSV - re-enable for others
360     # get node-name
361     # print Dumper($self);
362     #print Dumper($self->{meta}->{$partner});
363     #print "ΓΆΓΆ", $self->{meta}->{$partner}->{node}, "\n";
364     my $nodename = $self->{meta}->{$partner}->{node};
365     # check if nodename is actually a CODEref, execute it to get a mapped/filtered target-nodename
366    
367     #print "nodename: $nodename", "\n";
368    
369     $logger->info( __PACKAGE__ . "->syncNodes: Accessing dbType=\"$dbType\", nodename=\"$nodename\"." );
370    
371     =pod
372     #print "----", ref $nodename, "\n";
373     if ($nodename =~ m/CODE/) {
374     print Dumper($self);
375     #exit;
376     $nodename = $nodename->($nodename);
377     }
378     =cut
379    
380     if (!$self->{meta}->{$partner}->{storage}->existsChildNode($nodename)) {
381     $logger->critical( __PACKAGE__ . "->syncNodes: Could not reach node \"$nodename\" at partner \"$partner\"." );
382     return;
383     }
384    
385     }
386    
387     # TODO:
388     # + if action == PUSH: start processing
389     # -+ if action == PULL: swap metadata and start processing
390     # - if action == FULL: start processing, then swap metadata and (re-)start processing
391    
392     #print Dumper($self->{args});
393    
394     # manipulate metainfo according to direction of synchronization
395     if (lc $self->{args}->{direction} eq 'push') {
396     # just do it ...
397     } elsif (lc $self->{args}->{direction} eq 'pull') {
398     #print "=======SWAP", "\n";
399     # swap
400     ($self->{meta}->{source}, $self->{meta}->{target}) =
401     ($self->{meta}->{target}, $self->{meta}->{source});
402     } elsif (lc $self->{args}->{direction} eq 'full') {
403     } else {
404     }
405    
406     # import flag means: prepare the source node to be syncable
407     # this is useful if there are e.g. no "ident" or "checksum" columns yet inside a DBI like (row-based) storage
408     if ($self->{args}->{prepare}) {
409     $self->_prepareNode_MetaProperties('source');
410     $self->_prepareNode_DummyIdent('source');
411     #return;
412     #$self->_erase_all($opts->{source_node});
413     }
414    
415     # erase flag means: erase the target
416     #if ($opts->{erase}) {
417     if ($self->{args}->{erase}) {
418     # TODO: move this method to the scope of the synchronization core and wrap it around different handlers
419     #print "ERASE", "\n";
420     $self->_erase_all('target');
421     }
422    
423     $self->_syncNodes();
424    
425     }
426    
427     1;

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