--- nfo/perl/libs/Data/Transfer/Sync/Core.pm 2003/02/14 14:03:49 1.6 +++ nfo/perl/libs/Data/Transfer/Sync/Core.pm 2004/06/19 16:53:38 1.13 @@ -1,11 +1,36 @@ -## $Id: Core.pm,v 1.6 2003/02/14 14:03:49 joko Exp $ +## ------------------------------------------------------------------------- +## +## $Id: Core.pm,v 1.13 2004/06/19 16:53:38 joko Exp $ ## ## Copyright (c) 2002 Andreas Motl ## ## See COPYRIGHT section in pod text below for usage and distribution rights. ## -## ---------------------------------------------------------------------------------------- +## ------------------------------------------------------------------------- ## $Log: Core.pm,v $ +## Revision 1.13 2004/06/19 16:53:38 joko +## fix: handle local checksum only if database is configured with "hasLocalChecksum" +## +## Revision 1.12 2004/06/19 01:45:08 joko +## introduced "local checksum"-mechanism +## moved _dumpCompact to ::Compare::Checksum +## +## Revision 1.11 2004/05/11 20:03:48 jonen +## bugfix[joko] related to Attribute Map +## +## Revision 1.10 2003/06/25 23:03:57 joko +## no debugging +## +## Revision 1.9 2003/05/13 08:17:52 joko +## buildAttributeMap now propagates error +## +## Revision 1.8 2003/03/27 15:31:15 joko +## fixes to modules regarding new namespace(s) below Data::Mungle::* +## +## Revision 1.7 2003/02/21 08:01:11 joko +## debugging, logging +## renamed module +## ## Revision 1.6 2003/02/14 14:03:49 joko ## + logging, debugging ## - refactored code to sister module @@ -59,7 +84,7 @@ ## + minor cosmetics for logging ## ## Revision 1.2 2002/12/01 04:43:25 joko -## + mapping deatil entries may now be either an ARRAY or a HASH +## + mapping detail entries may now be either an ARRAY or a HASH ## + erase flag is used now (for export-operations) ## + expressions to refer to values inside deep nested structures ## - removed old mappingV2-code @@ -71,7 +96,7 @@ ## ## Revision 1.1 2002/10/10 03:44:21 cvsjoko ## + new -## ---------------------------------------------------------------------------------------- +## ------------------------------------------------------------------------- package Data::Transfer::Sync::Core; @@ -86,11 +111,13 @@ use Data::Dumper; -use misc::HashExt; -use Data::Compare::Struct qw( getDifference isEmpty ); +#use misc::HashExt; +use Hash::Serializer; +use Data::Mungle::Compare::Struct qw( getDifference isEmpty ); +use Data::Mungle::Transform::Deep qw( deep_copy expand ); use Data::Storage::Container; use DesignPattern::Object; -use libdb qw( quotesql ); +use shortcuts::database qw( quotesql ); # get logger instance my $logger = Log::Dispatch::Config->instance; @@ -152,7 +179,7 @@ $logger->debug( __PACKAGE__ . "->_run" ); # for statistics - my $tc = OneLineDumpHash->new( {} ); + my $tc = Hash::Serializer->new( {} ); my $results; # set of objects is already in $self->{args} @@ -175,7 +202,8 @@ return; } - + #print Dumper(@$results); + #exit; # check if we actually *have* a synchronization method if (!$self->{options}->{metadata}->{syncMethod}) { @@ -186,15 +214,18 @@ # dereference my @results = @{$results}; + #print Dumper(@results); # iterate through set foreach my $source_node_real (@results) { print ":" if $self->{verbose}; + #print Dumper($source_node_real); + $tc->{total}++; -#print "======================== iter", "\n"; + #print "=" x 80, "\n"; # clone object (in case we have to modify it here) # TODO: @@ -203,12 +234,13 @@ # - after all, just take care for now that this object doesn't get updated! # - so, just use its reference for now - if some cloning is needed in future, do this here! my $source_node = $source_node_real; + #my $source_node = expand($source_node_real); # modify entry - handle new style callbacks (the readers) # trace - #print Dumper($source_node); - #exit; + #print Dumper($source_node); + #exit; my $descent = 'source'; @@ -224,6 +256,8 @@ foreach my $node (keys %{$callbacks->{read}}) { + #print "cb_node: $node", "\n"; + my $object = $source_node; my $value; # = $source_node->{$node}; @@ -281,18 +315,20 @@ print "n" if $self->{verbose}; } -#print "checksum", "\n"; - - #print Dumper($self); - # determine status of entry by synchronization method if ( lc $self->{options}->{metadata}->{syncMethod} eq 'checksum' ) { #if ( $statOK && (lc $self->{args}->{method} eq 'checksum') ) { #if ( !$self->{node}->{status}->{new} && (lc $self->{args}->{method} eq 'checksum') ) { + # new 2004-06-17: calculate local checksum of source node + # new 2004-06-19: ... only if requested + if ($self->{options}->{source}->{storage}->{handle}->{locator}->{hasLocalChecksum}) { + $self->handleLocalChecksum('source'); + } + # calculate checksum of source node #$self->_calcChecksum('source'); - if (!$self->_readChecksum('source')) { + if (!$self->readChecksum('source')) { $logger->warning( __PACKAGE__ . "->_run: Could not find \"source\" entry with ident=\"$self->{node}->{source}->{ident}\"" ); $tc->{skip}++; print "s" if $self->{verbose}; @@ -300,9 +336,9 @@ } # get checksum from synchronization target - $self->_readChecksum('target'); - #if (!$self->_readChecksum('target')) { - # $logger->critical( __PACKAGE__ . "->_readChecksum: Could not find \"target\" entry with ident=\"$self->{node}->{source}->{ident}\"" ); + $self->readChecksum('target'); + #if (!$self->readChecksum('target')) { + # $logger->critical( __PACKAGE__ . "->readChecksum: Could not find \"target\" entry with ident=\"$self->{node}->{source}->{ident}\"" ); # next; #} @@ -319,7 +355,10 @@ # trace #print Dumper($self->{node}); #exit; + #print "LOCAL: ", $self->{node}->{source}->{checksum_local_storage}, " <-> ", $self->{node}->{source}->{checksum_local_calculated}, "\n"; + #print "REMOTE: ", $self->{node}->{source}->{checksum}, " <-> ", $self->{node}->{target}->{checksum}, "\n"; + # calculate new/dirty status $self->{node}->{status}->{new} = !$self->{node}->{target}->{checksum}; if (!$self->{node}->{status}->{new}) { $self->{node}->{status}->{dirty} = @@ -329,12 +368,26 @@ $self->{args}->{force}; } + # new 2004-06-17: also check if local checksum is inconsistent + # new 2004-06-19: ... only if requested + if ($self->{options}->{source}->{storage}->{handle}->{locator}->{hasLocalChecksum} and + ($self->{node}->{source}->{checksum_local_storage} ne $self->{node}->{source}->{checksum_local_calculated}) ) { + $self->{node}->{status}->{dirty_local} = 1; + $self->{node}->{status}->{dirty} = 1; + } + } else { $logger->warning( __PACKAGE__ . "->_run: Synchronization method '$self->{options}->{metadata}->{syncMethod}' is not implemented" ); $tc->{skip}++; print "s" if $self->{verbose}; next; - + } + + # new 2004-06-17: also update local checksum + if ($self->{node}->{status}->{dirty_local}) { + $tc->{locally_modified}++; + print "[lm]" if $self->{verbose}; + $self->_doModify_LocalChecksum('source'); } # first reaction on entry-status: continue with next entry if the current is already "in sync" @@ -343,9 +396,17 @@ next; } - # build map to actually transfer the data from source to target - $self->buildAttributeMap(); + #print Dumper($self->{node}->{source}); + # build map to actually transfer the data from source to target + if (!$self->buildAttributeMap()) { + #$logger->warning( __PACKAGE__ . "->_run: Attribute Map could not be created. Will not insert or modify node."); + push( @{$tc->{error_per_row}}, "Attribute Map could not be created. Will not insert or modify node $self->{node}->{source}->{ident}."); + #push( @{$tc->{error_per_row}}, "Attribute Map could not be created. Will not insert or modify node " . Dumper($self->{node}->{source}) . "."); + $tc->{error}++; + print "e" if $self->{verbose}; + next; + } # trace #print Dumper($self->{node}); exit; @@ -373,14 +434,14 @@ # asymmetry: refetch node from target to re-calculate new ident and checksum (TODO: is IdentAuthority of relevance here?) #print Dumper($self->{node}); $self->_statloadNode('target', $self->{node}->{target}->{ident}, 1); - $self->_readChecksum('target'); + $self->readChecksum('target'); } elsif ($self->{node}->{status}->{dirty}) { $tc->{attempt_modify}++; # asymmetry: get ident before updating (TODO: is IdentAuthority of relevance here?) $self->{node}->{target}->{ident} = $self->{node}->{map}->{$self->{meta}->{target}->{IdentProvider}->{arg}}; $self->_doTransferToTarget('update'); - $self->_readChecksum('target'); + $self->readChecksum('target'); } if ($self->{node}->{status}->{ok}) { @@ -408,6 +469,9 @@ #exit; $self->_doModifySource_IdentChecksum($self->{node}->{target}->{ident}); } + + #print "UNLOAD", "\n"; + #$self->{meta}->{source}->{storage}->unload( $self->{node}->{source}->{payload} ); } @@ -424,58 +488,14 @@ # todo!!! #sysevent( { usermsg => $msg, level => $level }, $taskEvent ); - $logger->info( __PACKAGE__ . "->_run: $msg" ); + #$logger->info( __PACKAGE__ . "->_run: $msg" ); + $logger->info($msg . "\n"); return $tc; } -# refactor this as some core-function to do a generic dump resolving data-encapsulations of e.g. Set::Object -sub _dumpCompact { - my $self = shift; - - #my $vars = \@_; - my @data = (); - - my $count = 0; - foreach (@_) { - my $item = {}; - foreach my $key (keys %$_) { - my $val = $_->{$key}; - -#print Dumper($val); - - if (ref $val eq 'Set::Object') { - #print "========================= SET", "\n"; -#print Dumper($val); - #print Dumper($val->members()); - #$val = $val->members(); - #$vars->[$count]->{$key} = $val->members() if $val->can("members"); - #$item->{$key} = $val->members() if $val->can("members"); - $item->{$key} = $val->members(); - #print Dumper($vars->[$count]->{$key}); - - } else { - $item->{$key} = $val; - } - - } - push @data, $item; - $count++; - } - -#print "Dump:", Dumper(@data), "\n"; - - $Data::Dumper::Indent = 0; - my $result = Dumper(@data); - $Data::Dumper::Indent = 2; - return $result; - -} - - - sub _doTransferToTarget { my $self = shift; my $action = shift; @@ -508,7 +528,14 @@ $self->_modifyNode('source', 'update', $map); } - +sub _doModify_LocalChecksum { + my $self = shift; + my $descent = shift; + my $map = { + cs_local => $self->{node}->{$descent}->{checksum_local_calculated}, + }; + $self->_modifyNode($descent, 'update', $map); +} sub _prepareNode_MetaProperties { my $self = shift; @@ -544,10 +571,12 @@ } +# TODO: load column-metadata from reversed mapping-metadata sub _prepareNode_DummyIdent { my $self = shift; my $descent = shift; + #print Dumper($self->{options}); $logger->info( __PACKAGE__ . "->_prepareNode_DummyIdent( descent $descent )" ); my $list = $self->_getNodeList($descent); @@ -561,6 +590,7 @@ my $map = { $self->{meta}->{$descent}->{IdentProvider}->{arg} => $ident_dummy, cs => undef, + cs_local => undef, }; # diff lists and ...