[#346] do not rely on creation property for filesystem version diff

fixes #346
fixes #358
This commit is contained in:
Christian Schwarz 2020-08-23 19:21:55 +02:00
parent 6b4c6fc062
commit 3f8fe3a368

View File

@ -77,56 +77,48 @@ func IncrementalPath(receiver, sender []*FilesystemVersion) (incPath []*Filesyst
receiver = SortVersionListByCreateTXGThenBookmarkLTSnapshot(receiver) receiver = SortVersionListByCreateTXGThenBookmarkLTSnapshot(receiver)
sender = SortVersionListByCreateTXGThenBookmarkLTSnapshot(sender) sender = SortVersionListByCreateTXGThenBookmarkLTSnapshot(sender)
// Find most recent common ancestor by name, preferring snapshots over bookmarks var mrcaCandidate struct {
found bool
guid uint64
r, s int
}
mrcaRcv := len(receiver) - 1 findCandidate:
mrcaSnd := len(sender) - 1 for r := len(receiver) - 1; r >= 0; r-- {
for s := len(sender) - 1; s >= 0; s-- {
for mrcaRcv >= 0 && mrcaSnd >= 0 { if sender[s].GetGuid() == receiver[r].GetGuid() {
if receiver[mrcaRcv].Guid == sender[mrcaSnd].Guid { mrcaCandidate.guid = sender[s].GetGuid()
// Since we arrive from the end of the array, and because we defined bookmark < snapshot, mrcaCandidate.s = s
// this condition will match snapshot first, which is what we want because it gives us mrcaCandidate.r = r
// size estimation mrcaCandidate.found = true
break break findCandidate
} }
receiverCreation, err := receiver[mrcaRcv].CreationAsTime()
if err != nil {
panic(err) // FIXME move this to a sorting phase before
}
senderCreation, err := sender[mrcaSnd].CreationAsTime()
if err != nil {
panic(err) // FIXME move this to the sorting phase before
}
if receiverCreation.Before(senderCreation) {
mrcaSnd--
} else {
mrcaRcv--
} }
} }
if mrcaRcv == -1 || mrcaSnd == -1 { // handle failure cases
if !mrcaCandidate.found {
return nil, &ConflictNoCommonAncestor{ return nil, &ConflictNoCommonAncestor{
SortedSenderVersions: sender, SortedSenderVersions: sender,
SortedReceiverVersions: receiver, SortedReceiverVersions: receiver,
} }
} } else if mrcaCandidate.r != len(receiver)-1 {
if mrcaRcv != len(receiver)-1 {
return nil, &ConflictDiverged{ return nil, &ConflictDiverged{
SortedSenderVersions: sender, SortedSenderVersions: sender,
SortedReceiverVersions: receiver, SortedReceiverVersions: receiver,
CommonAncestor: sender[mrcaSnd], CommonAncestor: sender[mrcaCandidate.s],
SenderOnly: sender[mrcaSnd+1:], SenderOnly: sender[mrcaCandidate.s+1:],
ReceiverOnly: receiver[mrcaRcv+1:], ReceiverOnly: receiver[mrcaCandidate.r+1:],
} }
} }
// incPath is possible
// incPath must not contain bookmarks except initial one, // incPath must not contain bookmarks except initial one,
incPath = make([]*FilesystemVersion, 0, len(sender)) incPath = make([]*FilesystemVersion, 0, len(sender))
incPath = append(incPath, sender[mrcaSnd]) incPath = append(incPath, sender[mrcaCandidate.s])
// it's ok if incPath[0] is a bookmark, but not the subsequent ones in the incPath // it's ok if incPath[0] is a bookmark, but not the subsequent ones in the incPath
for i := mrcaSnd + 1; i < len(sender); i++ { for i := mrcaCandidate.s + 1; i < len(sender); i++ {
if sender[i].Type == FilesystemVersion_Snapshot && incPath[len(incPath)-1].Guid != sender[i].Guid { if sender[i].Type == FilesystemVersion_Snapshot && incPath[len(incPath)-1].Guid != sender[i].Guid {
incPath = append(incPath, sender[i]) incPath = append(incPath, sender[i])
} }