java-topology/defects/rclone-0002/patch/recheck_set.patch

69 lines
2.8 KiB
Diff

# UNDF: UNDF-2026-000001024
--- a/cmd/bisync/listing.go
+++ b/cmd/bisync/listing.go
@@ -727,8 +727,14 @@ func (b *bisyncRun) recheck(ctxRecheck context.Context, src, dst fs.Fs, srcList,
var srcObjs []fs.Object
var dstObjs []fs.Object
- var resolved []string
var toRollback []string
+ resolvedSet := make(map[string]struct{})
+
+ // Build a map from dstObj.Remote() to dstObj for O(1) lookup
+ // instead of O(S*D) nested loop
+ dstByRemote := make(map[string]fs.Object)
+ dstByAlias := make(map[string]fs.Object)
if err := operations.ListFn(ctxRecheck, src, func(obj fs.Object) {
srcObjs = append(srcObjs, obj)
@@ -740,29 +746,33 @@ func (b *bisyncRun) recheck(ctxRecheck context.Context, src, dst fs.Fs, srcList,
fs.Debugf(dst, "error recchecking dst obj: %v", err)
}
+ for _, dstObj := range dstObjs {
+ dstByRemote[dstObj.Remote()] = dstObj
+ alias := b.aliases.Alias(dstObj.Remote())
+ if alias != dstObj.Remote() {
+ dstByAlias[alias] = dstObj
+ }
+ }
+
putObj := func(obj fs.Object, list *fileList) {
hashVal := ""
if !b.opt.IgnoreListingChecksum {
@@ -760,18 +770,20 @@ func (b *bisyncRun) recheck(ctxRecheck context.Context, src, dst fs.Fs, srcList,
for _, srcObj := range srcObjs {
fs.Debugf(srcObj, "rechecking")
- for _, dstObj := range dstObjs {
- if srcObj.Remote() == dstObj.Remote() || srcObj.Remote() == b.aliases.Alias(dstObj.Remote()) {
- // note: unlike Equal(), WhichEqual() does not update the modtime in dest if sums match but modtimes don't.
- if b.opt.DryRun || b.WhichEqual(ctxRecheck, srcObj, dstObj, src, dst) {
- putObj(srcObj, srcList)
- putObj(dstObj, dstList)
- resolved = append(resolved, srcObj.Remote())
- } else {
- fs.Infof(srcObj, "files not equal on recheck: %v %v", srcObj, dstObj)
- }
+ remote := srcObj.Remote()
+ dstObj, found := dstByRemote[remote]
+ if !found {
+ dstObj, found = dstByAlias[remote]
+ }
+ if found {
+ // note: unlike Equal(), WhichEqual() does not update the modtime in dest if sums match but modtimes don't.
+ if b.opt.DryRun || b.WhichEqual(ctxRecheck, srcObj, dstObj, src, dst) {
+ putObj(srcObj, srcList)
+ putObj(dstObj, dstList)
+ resolvedSet[remote] = struct{}{}
+ } else {
+ fs.Infof(srcObj, "files not equal on recheck: %v %v", srcObj, dstObj)
}
}
- // if srcObj not resolved by now (either because no dstObj match or files not equal),
- // roll it back to old version, so it gets retried next time.
- // skip and error during --resync, as rollback is not possible
- if !slices.Contains(resolved, srcObj.Remote()) && !b.opt.DryRun {
+ if _, ok := resolvedSet[remote]; !ok && !b.opt.DryRun {
if b.opt.Resync {
err := errors.New("no dstObj match or files not equal")
b.handleErr(srcObj, "Unable to rollback during --resync", err, true, false)