github.com/hasnat/dolt/go@v0.0.0-20210628190320-9eb5d843fbb7/store/merge/three_way_ordered_sequence.go (about) 1 // Copyright 2019 Dolthub, Inc. 2 // 3 // Licensed under the Apache License, Version 2.0 (the "License"); 4 // you may not use this file except in compliance with the License. 5 // You may obtain a copy of the License at 6 // 7 // http://www.apache.org/licenses/LICENSE-2.0 8 // 9 // Unless required by applicable law or agreed to in writing, software 10 // distributed under the License is distributed on an "AS IS" BASIS, 11 // WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. 12 // See the License for the specific language governing permissions and 13 // limitations under the License. 14 // 15 // This file incorporates work covered by the following copyright and 16 // permission notice: 17 // 18 // Copyright 2016 Attic Labs, Inc. All rights reserved. 19 // Licensed under the Apache License, version 2.0: 20 // http://www.apache.org/licenses/LICENSE-2.0 21 22 package merge 23 24 import ( 25 "context" 26 "fmt" 27 28 "golang.org/x/sync/errgroup" 29 30 "github.com/dolthub/dolt/go/store/d" 31 "github.com/dolthub/dolt/go/store/types" 32 ) 33 34 type applyFunc func(candidate, types.ValueChanged, types.Value) (candidate, error) 35 36 func (m *merger) threeWayOrderedSequenceMerge(ctx context.Context, a, b, parent candidate, apply applyFunc, path types.Path) (types.Value, error) { 37 aChangeChan, bChangeChan := make(chan types.ValueChanged), make(chan types.ValueChanged) 38 39 eg, ctx := errgroup.WithContext(ctx) 40 eg.Go(func() error { 41 defer close(aChangeChan) 42 return a.diff(ctx, parent, aChangeChan) 43 }) 44 eg.Go(func() error { 45 defer close(bChangeChan) 46 return b.diff(ctx, parent, bChangeChan) 47 }) 48 49 merged := parent 50 eg.Go(func() error { 51 aChange, bChange := types.ValueChanged{}, types.ValueChanged{} 52 for { 53 // Get the next change from both a and b. If either diff(a, 54 // parent) or diff(b, parent) is complete, aChange or bChange 55 // will get an empty types.ValueChanged containing a nil Value. 56 // Generally, though, this allows us to proceed through both 57 // diffs in (key) order, considering the "current" change from 58 // both diffs at the same time. 59 if aChange.Key == nil { 60 select { 61 case aChange = <-aChangeChan: 62 case <-ctx.Done(): 63 return ctx.Err() 64 } 65 } 66 if bChange.Key == nil { 67 select { 68 case bChange = <-bChangeChan: 69 case <-ctx.Done(): 70 return ctx.Err() 71 } 72 } 73 74 // Both channels are producing zero values, so we're done. 75 if aChange.Key == nil && bChange.Key == nil { 76 break 77 } 78 79 // Since diff generates changes in key-order, and we 80 // never skip over a change without processing it, we 81 // can simply compare the keys at which aChange and 82 // bChange occurred to determine if either is safe to 83 // apply to the merge result without further 84 // processing. This is because if, e.g. 85 // aChange.V.Less(bChange.V), we know that the diff of 86 // b will never generate a change at that key. If it 87 // was going to, it would have done so on an earlier 88 // iteration of this loop and been processed at that 89 // time. 90 // 91 // It's also obviously OK to apply a change if only one 92 // diff is generating any changes, e.g. aChange.V is 93 // non-nil and bChange.V is nil. 94 if aChange.Key != nil { 95 var err error 96 noBOrALessB := bChange.Key == nil 97 if !noBOrALessB { 98 noBOrALessB, err = aChange.Key.Less(m.vrw.Format(), bChange.Key) 99 if err != nil { 100 return err 101 } 102 } 103 104 if noBOrALessB { 105 v, _, err := a.get(ctx, aChange.Key) 106 if err != nil { 107 return err 108 } 109 110 merged, err = apply(merged, aChange, v) 111 if err != nil { 112 return err 113 } 114 115 aChange = types.ValueChanged{} 116 continue 117 } 118 } 119 120 if bChange.Key != nil { 121 var err error 122 noAOrBLessA := aChange.Key == nil 123 124 if !noAOrBLessA { 125 noAOrBLessA, err = bChange.Key.Less(m.vrw.Format(), aChange.Key) 126 if err != nil { 127 return err 128 } 129 } 130 131 if noAOrBLessA { 132 v, _, err := b.get(ctx, bChange.Key) 133 if err != nil { 134 return err 135 } 136 137 merged, err = apply(merged, bChange, v) 138 if err != nil { 139 return err 140 } 141 142 bChange = types.ValueChanged{} 143 continue 144 } 145 } 146 147 if !aChange.Key.Equals(bChange.Key) { 148 d.Panic("Diffs have skewed!") // Sanity check. 149 } 150 151 change, mergedVal, err := m.mergeChanges(ctx, aChange, bChange, a, b, parent, apply, path) 152 if err != nil { 153 return err 154 } 155 merged, err = apply(merged, change, mergedVal) 156 if err != nil { 157 return err 158 } 159 160 aChange, bChange = types.ValueChanged{}, types.ValueChanged{} 161 } 162 return nil 163 }) 164 165 if err := eg.Wait(); err != nil { 166 return nil, err 167 } 168 169 return merged.getValue(), nil 170 } 171 172 func (m *merger) mergeChanges(ctx context.Context, aChange, bChange types.ValueChanged, a, b, p candidate, apply applyFunc, path types.Path) (change types.ValueChanged, mergedVal types.Value, err error) { 173 path, err = a.pathConcat(ctx, aChange, path) 174 175 if err != nil { 176 return types.ValueChanged{}, nil, err 177 } 178 179 aValue, _, err := a.get(ctx, aChange.Key) 180 181 if err != nil { 182 return types.ValueChanged{}, nil, err 183 } 184 185 bValue, _, err := b.get(ctx, bChange.Key) 186 187 if err != nil { 188 return types.ValueChanged{}, nil, err 189 } 190 191 // If the two diffs generate different kinds of changes at the same key, conflict. 192 if aChange.ChangeType != bChange.ChangeType { 193 if change, mergedVal, ok := m.resolve(aChange.ChangeType, bChange.ChangeType, aValue, bValue, path); ok { 194 // TODO: Correctly encode Old/NewValue with this change report. https://github.com/attic-labs/noms/issues/3467 195 return types.ValueChanged{ChangeType: change, Key: aChange.Key, OldValue: nil, NewValue: nil}, mergedVal, nil 196 } 197 198 aDesc, err := describeChange(aChange) 199 200 if err != nil { 201 return types.ValueChanged{}, nil, err 202 } 203 204 bDesc, err := describeChange(bChange) 205 206 if err != nil { 207 return types.ValueChanged{}, nil, err 208 } 209 210 return change, nil, newMergeConflict("Conflict:\n%s\nvs\n%s\n", aDesc, bDesc) 211 } 212 213 if aChange.ChangeType == types.DiffChangeRemoved || aValue.Equals(bValue) { 214 // If both diffs generated a remove, or if the new value is the same in both, merge is fine. 215 return aChange, aValue, nil 216 } 217 218 // There's one case that might still be OK even if aValue and bValue differ: different, but mergeable, compound values of the same type being added/modified at the same key, e.g. a Map being added to both a and b. If either is a primitive, or Values of different Kinds were added, though, we're in conflict. 219 if !unmergeable(aValue, bValue) { 220 v, _, err := p.get(ctx, aChange.Key) 221 222 if err != nil { 223 return types.ValueChanged{}, nil, err 224 } 225 226 // TODO: Add concurrency. 227 if mergedVal, err = m.threeWay(ctx, aValue, bValue, v, path); err == nil { 228 return aChange, mergedVal, nil 229 } 230 return change, nil, err 231 } 232 233 if change, mergedVal, ok := m.resolve(aChange.ChangeType, bChange.ChangeType, aValue, bValue, path); ok { 234 // TODO: Correctly encode Old/NewValue with this change report. https://github.com/attic-labs/noms/issues/3467 235 return types.ValueChanged{ChangeType: change, Key: aChange.Key, OldValue: nil, NewValue: nil}, mergedVal, nil 236 } 237 238 aStr, err := types.EncodedValue(ctx, aValue) 239 240 if err != nil { 241 return types.ValueChanged{}, nil, err 242 } 243 244 aDesc, err := describeChange(aChange) 245 246 if err != nil { 247 return types.ValueChanged{}, nil, err 248 } 249 250 bStr, err := types.EncodedValue(ctx, bValue) 251 252 if err != nil { 253 return types.ValueChanged{}, nil, err 254 } 255 256 bDesc, err := describeChange(bChange) 257 258 if err != nil { 259 return types.ValueChanged{}, nil, err 260 } 261 262 return change, nil, newMergeConflict("Conflict:\n%s = %s\nvs\n%s = %s", aDesc, aStr, bDesc, bStr) 263 } 264 265 func describeChange(change types.ValueChanged) (string, error) { 266 op := "" 267 switch change.ChangeType { 268 case types.DiffChangeAdded: 269 op = "added" 270 case types.DiffChangeModified: 271 op = "modded" 272 case types.DiffChangeRemoved: 273 op = "removed" 274 } 275 276 str, err := types.EncodedValue(context.Background(), change.Key) 277 278 if err != nil { 279 return "", err 280 } 281 282 return fmt.Sprintf("%s %s", op, str), nil 283 }