[Bps-public-commit] r10942 - in SVN-PropDB: bin lib/SVN/PropDB
jesse at bestpractical.com
jesse at bestpractical.com
Wed Feb 27 12:20:15 EST 2008
Author: jesse
Date: Wed Feb 27 12:20:14 2008
New Revision: 10942
Modified:
SVN-PropDB/ (props changed)
SVN-PropDB/bin/merger
SVN-PropDB/lib/SVN/PropDB/Record.pm
Log:
r27968 at 31b: jesse | 2008-02-26 13:27:01 -0500
checkpoint
Modified: SVN-PropDB/bin/merger
==============================================================================
--- SVN-PropDB/bin/merger (original)
+++ SVN-PropDB/bin/merger Wed Feb 27 12:20:14 2008
@@ -15,47 +15,198 @@
$local_source->snapshot;
$remote_source->snapshot;
-my @deltas_to_integrate = $remote_source->fetch_deltas(after => $remote_source->last_delta_seen);
+my @txns_to_integrate = $remote_source->fetch_txns(after => $remote_source->last_txn_seen);
-for my $delta (@deltas_to_integrate) {
- next if ($local_source->has_seen($delta) );
- if ($local_source->delta_will_conflict($delta)) {
+for my $txn (@txns_to_integrate) {
+ next if ($local_source->has_seen_txn($txn) );
+ if ($local_source->txn_will_conflict($txn)) {
+ die "Conflicts are hard";
# make a decision about who wins the conflict
- # For parts of the conflict _remote_ should win, write out a nullification delta beforehand,
- # apply the delta. it will now apply cleanly
+ # For parts of the conflict _remote_ should win, write out a nullification txn beforehand,
+ # apply the txn. it will now apply cleanly
# For parts of the conflict _local_ should win,
- # write out a nullification delta beforehand,
+ # write out a nullification txn beforehand,
# - that way, the remote update will apply cleanly
- # Then write out the remote delta
- # Then write out a new delta which reverts the parts of the remote delta which local should win
+ # Then write out the remote txn
+ # Then write out a new txn which reverts the parts of the remote txn which local should win
} else {
- $local_source->apply_delta($delta);
+ $local_source->apply_txn($txn);
}
}
-if ( $remote_source->accepts_deltas ) {
- my @deltas_to_send = $local_source->fetch_deltas( after =>
- $remote_source->last_delta_received( source => $local_source ) );
-
- for my $delta (@deltas_to_send) {
- next if ( $remote_source->has_seen($delta) );
- if ( $remote_source->delta_will_conflict($delta) ) {
- What we need to do here is:
- a good fucking question
-
-
-
+if ( $remote_source->accepts_txns ) {
+ my @txns_to_send = $local_source->fetch_txns( after =>
+ $remote_source->last_txn_received( source => $local_source ) );
+
+ for my $txn (@txns_to_send) {
+ next if ( $remote_source->has_seen_txn($txn) );
+ if ( $remote_source->txn_will_conflict($txn) ) {
+ die "Conflicts are hard"
} else {
- $remote_source->apply_delta($delta);
+ $remote_source->apply_txn($txn);
}
}
}
+package SVN::PropDB::MergeSource;
+use base 'Class::Accessor';
+
+__PACKAGE__->mk_accessors(qw'url unique_id');
+
+sub accepts_txns {}
+sub has_seen_txn {}
+sub txn_will_conflict {}
+sub apply_txn {}
+sub fetch_txns {}
+sub last_txn_received {}
+
+
+=head2 Assumptions about merge sources
+
+ - a source represents a branch
+ - a branch has had many revisions applied
+ - revisions we apply to a branch from another branch are always applied UNCHANGED
+ - in the event of a conflict, we will apply a "pre-txn" to smooth the application and a "post-txn" if the applied txn doesn't match the desired outcome.
+
+ on pull
+ we end up applying every single remote txn this peer has seen since the last time we saw this peer, one by one
+ we possibly apply another two txns for each txn to smooth the application
+
+
+
+ we skip any remote txn we've seen from another source before
+
+
+ on push,
+ we publish each txn we've made locally.
+ - including "after" fixup txns
+ - not including "before" fixup txns.
+
+
+
+
+
+
+=head2 assumptions about merge txns
+
+we can get (and hash):
+ -original database uuid
+ -original database revno
+ -original database author
+ -all changes
+
+
+
+
+
+
+Audrey at 1:
+
+ Createdb
+ Add ticket 1 - subject 'foo'; status 'new'
+
+
+Jesse at 1:
+
+ j pull from a at 1
+
+ j at 1 - foo;new
+ a at 1 - foo;new
+
+ j at 2 foo->bar
+ a at 2 foo->baz
+
+ c at 1 pull from j at 2
+
+ c now has:
+ a at 1
+ j at 2
+
+
+ c at 2 bar->frotz
+
+ c at 3 pull from a at 2
+
+ a hands c: a at 2:foo->baz
+
+ Conflict
+
+ to local c applies a pre-fixup:
+ frotz->foo
+ to local c applies a at 2:
+ foo->baz
+ to local c applies a conflict resolution
+ baz->frotz
+
+
+ c at 4 push to a at 2
+
+ beforehand, a's state: baz
+ beforehand, c's state: frotz
+
+ beforehand, c's unpushed transactions:
+ j at 2 foo->bar
+ c at 2 bar->frotz
+ c at 3
+ pre-fixup: frotz->foo
+ a at 2: foo->baz
+ post-fixup: baz->frotz
+
+ so, what do we push?
+ options:
+ fixup to get a to our earliest state unpushed. that's kind of stupid and results in us replaying everthing all the time.
+ compute a single large txn from a at HEAD to c at HEAD and apply that?
+
+
+
+investigate "rumor" peer to peer replication
+
+
+take 2
+
+ there's a new peer I've not seen before. I need to merge in all their changes:
+
+ if a txn comes from a replica at rev lower than our last-seen version for replica, skip it
+
+ for each of their txns, import it, applying fixups as needed
+
+
+=head3 push
+
+ get the remote list of all merge tickets.
+ find all local revs which remote has never seen.
+ - genuine local txns
+ - third-party txns that the remote has no merge ticket for
+
+ - skip "before" fixup txns
+ - include "after" fixup txns, since they're merge resolutions
+
+
+ iterate over these revs the remote has never seen.
+ when the txn applies cleanly, just apply it.
+
+ when the txn does _not_ apply cleanly,
+ - apply a 'before' fix up transaction
+ - apply the original txn
+ - apply a merge resolution txn.
+ - TODO: this doesn't feel quite right
+ - the resolution should be the same as the equivalent merge resolution transaction on the "pull" variant if it exists.
+ What info do we have here?
+ - record uuid
+ - nearest parent variant
+ - local variant
+ - remote variant
+ - information from the 'future (local head)' about the eventual desired outcome
+
+ - audit stage:
+ compare local head and remote head. - they should now be identical, since the last transactions we replayed were all local merge fixup txns. (is that true?)
+
+=cut
Modified: SVN-PropDB/lib/SVN/PropDB/Record.pm
==============================================================================
--- SVN-PropDB/lib/SVN/PropDB/Record.pm (original)
+++ SVN-PropDB/lib/SVN/PropDB/Record.pm Wed Feb 27 12:20:14 2008
@@ -93,6 +93,7 @@
my $props = shift;
my $errors = {};
for my $key (keys %$props) {
+ return undef unless ($self->_validate_prop_name($key));
if (my $sub = $self->can('validate_'.$key)) {
$sub->($self, props => $props, errors => $errors) || return undef;
}
@@ -101,6 +102,8 @@
}
+sub _validate_prop_name { 1}
+
sub _canonicalize_props {
my $self = shift;
my $props = shift;
More information about the Bps-public-commit
mailing list