[Bps-public-commit] r11815 - in Prophet/trunk: .
jesse at bestpractical.com
jesse at bestpractical.com
Tue Apr 22 10:53:24 EDT 2008
Author: jesse
Date: Tue Apr 22 10:53:21 2008
New Revision: 11815
Modified:
Prophet/trunk/ (props changed)
Prophet/trunk/lib/Prophet/Replica.pm
Log:
r29966 at 31b: jesse | 2008-04-22 16:14:12 +0200
* added a 'log' method which outputs log messages to STDERR if $ENV{'PROPHET_DEBUG'} is enabled.
* removed the half-assed 'debug' function
* cleaned up metadata storage functions to actually check if records exist rather than just eval {} around it
* cleaned up metadata storage functions to have correct create vs set logic
* modified the "should we integrate this change" logic to
- skip ALL merge tickets (they're automatically created as the changes they reference are integrated)
- use an API rather than massage the insides of a $changeset
Modified: Prophet/trunk/lib/Prophet/Replica.pm
==============================================================================
--- Prophet/trunk/lib/Prophet/Replica.pm (original)
+++ Prophet/trunk/lib/Prophet/Replica.pm Tue Apr 22 10:53:21 2008
@@ -157,6 +157,9 @@
my $changeset = $args{'changeset'};
+
+ $self->log("Considering changeset ".$changeset->original_sequence_no . " from " . substr($changeset->original_source_uuid,0,6));
+
# when we start to integrate a changeset, we need to do a bit of housekeeping
# We never want to merge in:
# merge tickets that describe merges from the local record
@@ -168,12 +171,15 @@
# we'll want to skip or remove those changesets
return if $changeset->original_source_uuid eq $self->uuid;
- return if ( $changeset->is_empty or $changeset->is_nullification );
+ return if ($changeset->is_nullification);
$self->remove_redundant_data($changeset); #Things we have already seen
+ return if ($changeset->is_empty);
+
if ( my $conflict = $self->conflicts_from_changeset($changeset) ) {
+ $self->log("Integrating conflicting changeset ".$changeset->original_sequence_no . " from " . substr($changeset->original_source_uuid,0,6));
$args{conflict_callback}->($conflict) if $args{'conflict_callback'};
$conflict->resolvers( [ sub { $args{resolver}->(@_) } ] ) if $args{resolver};
if ( $args{resolver_class} ) {
@@ -203,6 +209,7 @@
$args{'reporting_callback'}->( changeset => $changeset, conflict => $conflict ) if ( $args{'reporting_callback'} );
} else {
+ $self->log("Integrating changeset ".$changeset->original_sequence_no . " from " . substr($changeset->original_source_uuid,0,6));
$self->record_changeset_and_integration($changeset);
$args{'reporting_callback'}->( changeset => $changeset ) if ( $args{'reporting_callback'} );
@@ -267,6 +274,8 @@
my $self = shift;
my ($changeset) = validate_pos( @_, { isa => "Prophet::ChangeSet" } );
+ $self->log("Checking to see if we've ever seen changeset " .$changeset->original_sequence_no . " from ".substr($changeset->original_source_uuid,0,6));
+
# If the changeset originated locally, we never want it
return 1 if $changeset->original_source_uuid eq $self->uuid;
@@ -320,13 +329,23 @@
sub remove_redundant_data {
my ( $self, $changeset ) = @_;
- # XXX: encapsulation
- $changeset->{changes} = [
- grep { $self->is_resdb || $_->record_type ne '_prophet_resolution' }
- grep { !( $_->record_type eq $MERGETICKET_METATYPE && $_->record_uuid eq $self->uuid ) }
- $changeset->changes
- ];
+ my @new_changes;
+ foreach my $change ($changeset->changes) {
+ # when would we run into resolution records in a nonresb? XXX
+ next if ($change->record_type eq '_prophet_resolution' && !$self->is_resdb);
+
+ # never integrate a merge ticket that comes from a foriegn database.
+ # implict merge tickets are the devil and are lies. Merge tickets are always generated locally
+ # by importing a change that originated on that replica
+ # (The actual annoying technical problem is that the locally created merge ticket is written out in a separate transaction
+ # at ~ the same time as the original imported one is being written.
+ # This makes svn go boom
+ next if( $change->record_type eq $MERGETICKET_METATYPE);# && $change->record_uuid eq $self->uuid );
+ push (@new_changes, $change);
+ }
+
+ $changeset->changes(\@new_changes);
}
@@ -354,6 +373,10 @@
# XXX TODO
}
+
+ $self->log("Evaluating changesets to apply to ".substr($args{'for'}->uuid,0,6). " starting with ". $args{for}->last_changeset_from_source( $self->uuid ));
+
+
$self->traverse_changesets(
after => $args{for}->last_changeset_from_source( $self->uuid ),
callback => sub {
@@ -392,6 +415,8 @@
sub should_send_changeset {
my $self = shift;
my %args = validate( @_, { to => { isa => 'Prophet::Replica' }, changeset => { isa => 'Prophet::ChangeSet' } } );
+
+ $self->log("Should I send " .$args{changeset}->original_sequence_no . " from ".substr($args{changeset}->original_source_uuid,0,6) . " to " .substr($args{'to'}->uuid, 0, 6));
return undef if ( $args{'changeset'}->is_nullification || $args{'changeset'}->is_resolution );
return undef if $args{'to'}->has_seen_changeset( $args{'changeset'} );
@@ -471,6 +496,9 @@
sub traverse_changesets {
+ Carp::confess "Someone has failed to implement a 'traverse_changesets' method for their replica type.";
+
+
}
=head2 can_write_changesets
@@ -572,11 +600,15 @@
my %new_props = map { $_->name => $_->new_value } $change->prop_changes;
if ( $change->change_type eq 'add_file' ) {
+ $self->log("add_file: " .$change->record_type. " " .$change->record_uuid);
$self->create_record( type => $change->record_type, uuid => $change->record_uuid, props => \%new_props);
} elsif ( $change->change_type eq 'add_dir' ) {
+ $self->log("(IGNORED) add_dir: " .$change->record_type. " " .$change->record_uuid);
} elsif ( $change->change_type eq 'update_file' ) {
+ $self->log("update_file: " .$change->record_type. " " .$change->record_uuid);
$self->set_record_props( type => $change->record_type, uuid => $change->record_uuid, props => \%new_props);
} elsif ( $change->change_type eq 'delete' ) {
+ $self->log("delete_file: " .$change->record_type. " " .$change->record_uuid);
$self->delete_record( type => $change->record_type, uuid => $change->record_uuid);
} else {
Carp::confess( " I have never heard of the change type: " . $change->change_type );
@@ -596,15 +628,10 @@
my ($changeset) = validate_pos( @_, { isa => 'Prophet::ChangeSet' } );
# Record a merge ticket for the changeset's "original" source
- $self->_record_merge_ticket( $changeset->original_source_uuid, $changeset->original_sequence_no );
+ return $self->_record_metadata_for( $MERGETICKET_METATYPE, $changeset->original_source_uuid, 'last-changeset', $changeset->original_sequence_no );
}
-sub _record_merge_ticket {
- my $self = shift;
- my ( $source_uuid, $sequence_no ) = validate_pos( @_, 1, 1 );
- return $self->_record_metadata_for( $MERGETICKET_METATYPE, $source_uuid, 'last-changeset', $sequence_no );
-}
=head1 metadata storage routines
@@ -628,31 +655,40 @@
};
}
+
sub _retrieve_metadata_for {
my $self = shift;
my ( $name, $source_uuid, $prop_name ) = validate_pos( @_, 1, 1, 1 );
my $entry = Prophet::Record->new( handle => $self, type => $name );
- $entry->load( uuid => $source_uuid );
- return eval { $entry->prop($prop_name) };
+ unless ( $entry->load( uuid => $source_uuid )) {
+ return undef;
+ }
+
+ return $entry->prop($prop_name);
}
+
sub _record_metadata_for {
my $self = shift;
- my ( $name, $source_uuid, $prop_name, $content ) = validate_pos( @_, 1, 1, 1, 1 );
-
- my $props = eval { $self->get_record_props( uuid => $source_uuid, type => $name ) };
-
- # XXX: do set-prop when exists, and just create new record with all props is probably better
- unless ( $props->{$prop_name} ) {
- eval { $self->create_record( uuid => $source_uuid, type => $name, props => {} ) };
+ my ( $name, $source_uuid, $prop_name, $content )
+ = validate_pos( @_, 1, 1, 1, 1 );
+ $self->log( "Storing $content in $prop_name for $name " . substr( $source_uuid, 0, 6 ) );
+
+ if ( !$self->record_exists( type => $name, uuid => $source_uuid ) ) {
+ $self->log( "I don't have a $name for " . substr( $source_uuid, 0, 6 ) . "Creating it" );
+ $self->create_record(
+ uuid => $source_uuid,
+ type => $name, props => { $prop_name => $content }
+ );
+ } else {
+ $self->log( "Setting $prop_name to $content for $name for " . substr( $source_uuid, 0, 6 ) );
+ $self->set_record_props(
+ uuid => $source_uuid,
+ type => $name,
+ props => { $prop_name => $content }
+ );
}
-
- $self->set_record_props(
- uuid => $source_uuid,
- type => $name,
- props => { $prop_name => $content }
- );
}
@@ -738,9 +774,13 @@
sub _set_original_source_metadata_for_current_edit {}
-sub debug {
- warn $ENV{'PROPHET_USER'}." ". shift if $ENV{'PROPHET_DEBUG'};
+
+sub log {
+ my $self = shift;
+ my ($msg) = validate_pos(@_, 1);
+ print STDERR "# ".substr($self->uuid,0,6)." (".$self->scheme.":".$self->url." )".": " .$msg."\n" if ($ENV{'PROPHET_DEBUG'});
}
+
1;
More information about the Bps-public-commit
mailing list