From a1cb1d70c4f76ab9cff191f9662e7d8404a24f62 Mon Sep 17 00:00:00 2001 From: Simon Frei Date: Mon, 16 Mar 2020 08:45:45 +0100 Subject: [PATCH] lib/db: Use need func in withNeed and simplify (#6412) --- lib/db/transactions.go | 71 ++++++++++++++++-------------------------- 1 file changed, 26 insertions(+), 45 deletions(-) diff --git a/lib/db/transactions.go b/lib/db/transactions.go index bfacc3495..803c8abc3 100644 --- a/lib/db/transactions.go +++ b/lib/db/transactions.go @@ -8,11 +8,20 @@ package db import ( "bytes" + "fmt" "github.com/syncthing/syncthing/lib/db/backend" "github.com/syncthing/syncthing/lib/protocol" ) +type errDeviceEntryMissing struct { + name string +} + +func (err errDeviceEntryMissing) Error() string { + return fmt.Sprintf("device present in global list but missing as device/fileinfo entry: %s", err.name) +} + // A readOnlyTransaction represents a database snapshot. type readOnlyTransaction struct { backend.ReadTransaction @@ -344,53 +353,25 @@ func (t *readOnlyTransaction) withNeed(folder, device []byte, truncate bool, fn } haveFV, have := vl.Get(device) - // XXX: This marks Concurrent (i.e. conflicting) changes as - // needs. Maybe we should do that, but it needs special - // handling in the puller. - if have && haveFV.Version.GreaterEqual(vl.Versions[0].Version) { - continue - } name := t.keyer.NameFromGlobalVersionKey(dbi.Key()) - needVersion := vl.Versions[0].Version - needDevice := protocol.DeviceIDFromBytes(vl.Versions[0].Device) - - for i := range vl.Versions { - if !vl.Versions[i].Version.Equal(needVersion) { - // We haven't found a valid copy of the file with the needed version. - break - } - - if vl.Versions[i].Invalid { - // The file is marked invalid, don't use it. - continue - } - - dk, err = t.keyer.GenerateDeviceFileKey(dk, folder, vl.Versions[i].Device, name) - if err != nil { - return err - } - gf, ok, err := t.getFileTrunc(dk, truncate) - if err != nil { - return err - } - if !ok { - continue - } - - if gf.IsDeleted() && !have { - // We don't need deleted files that we don't have - break - } - - l.Debugf("need folder=%q device=%v name=%q have=%v invalid=%v haveV=%v globalV=%v globalDev=%v", folder, devID, name, have, haveFV.Invalid, haveFV.Version, needVersion, needDevice) - - if !fn(gf) { - return nil - } - - // This file is handled, no need to look further in the version list - break + dk, err = t.keyer.GenerateDeviceFileKey(dk, folder, vl.Versions[0].Device, name) + if err != nil { + return err + } + gf, ok, err := t.getFileTrunc(dk, truncate) + if err != nil { + return err + } + if !ok { + return errDeviceEntryMissing{string(name)} + } + if !need(gf, have, haveFV.Version) { + continue + } + l.Debugf("need folder=%q device=%v name=%q have=%v invalid=%v haveV=%v globalV=%v globalDev=%v", folder, devID, name, have, haveFV.Invalid, haveFV.Version, vl.Versions[0].Version, vl.Versions[0].Device) + if !fn(gf) { + return dbi.Error() } } return dbi.Error()