From f1b253fc0009e6e143b1e35d67599fb9c1970879 Mon Sep 17 00:00:00 2001 From: Jakob Borg Date: Fri, 20 Mar 2020 12:07:14 +0100 Subject: [PATCH] lib/db: Don't whack blocks when putting truncated file (#6434) As of the latest database checker we are again putting files without blocks. I'm not 100% convinced that's a great idea, but we also do it for ignored files apparently so it looks like we probably should support it. This adds an escape hatch that must be manually enabled... --- lib/db/db_test.go | 18 +++++++++++------- lib/db/lowlevel.go | 8 ++++---- lib/db/schemaupdater.go | 2 +- lib/db/transactions.go | 12 +++++++++--- 4 files changed, 25 insertions(+), 15 deletions(-) diff --git a/lib/db/db_test.go b/lib/db/db_test.go index 8b74a63e6..8efb052fc 100644 --- a/lib/db/db_test.go +++ b/lib/db/db_test.go @@ -261,11 +261,11 @@ func TestRepairSequence(t *testing.T) { short := protocol.LocalDeviceID.Short() files := []protocol.FileInfo{ - {Name: "fine"}, - {Name: "duplicate"}, - {Name: "missing"}, - {Name: "overwriting"}, - {Name: "inconsistent"}, + {Name: "fine", Blocks: genBlocks(1)}, + {Name: "duplicate", Blocks: genBlocks(2)}, + {Name: "missing", Blocks: genBlocks(3)}, + {Name: "overwriting", Blocks: genBlocks(4)}, + {Name: "inconsistent", Blocks: genBlocks(5)}, } for i, f := range files { files[i].Version = f.Version.Update(short) @@ -282,7 +282,7 @@ func TestRepairSequence(t *testing.T) { if err != nil { t.Fatal(err) } - if err := trans.putFile(dk, f); err != nil { + if err := trans.putFile(dk, f, false); err != nil { t.Fatal(err) } sk, err := trans.keyer.GenerateSequenceKey(nil, folder, seq) @@ -399,16 +399,20 @@ func TestRepairSequence(t *testing.T) { } defer it.Release() for it.Next() { - fi, ok, err := ro.getFileTrunc(it.Value(), true) + intf, ok, err := ro.getFileTrunc(it.Value(), false) if err != nil { t.Fatal(err) } + fi := intf.(protocol.FileInfo) seq := ro.keyer.SequenceFromSequenceKey(it.Key()) if !ok { t.Errorf("Sequence entry %v points at nothing", seq) } else if fi.SequenceNo() != seq { t.Errorf("Inconsistent sequence entry for %v: %v != %v", fi.FileName(), fi.SequenceNo(), seq) } + if len(fi.Blocks) == 0 { + t.Error("Missing blocks in", fi.FileName()) + } } if err := it.Error(); err != nil { t.Fatal(err) diff --git a/lib/db/lowlevel.go b/lib/db/lowlevel.go index f349a64b0..9c97e6bc1 100644 --- a/lib/db/lowlevel.go +++ b/lib/db/lowlevel.go @@ -114,7 +114,7 @@ func (db *Lowlevel) updateRemoteFiles(folder, device []byte, fs []protocol.FileI meta.addFile(devID, f) l.Debugf("insert; folder=%q device=%v %v", folder, devID, f) - if err := t.putFile(dk, f); err != nil { + if err := t.putFile(dk, f, false); err != nil { return err } @@ -201,7 +201,7 @@ func (db *Lowlevel) updateLocalFiles(folder []byte, fs []protocol.FileInfo, meta meta.addFile(protocol.LocalDeviceID, f) l.Debugf("insert (local); folder=%q %v", folder, f) - if err := t.putFile(dk, f); err != nil { + if err := t.putFile(dk, f, false); err != nil { return err } @@ -643,7 +643,7 @@ func (db *Lowlevel) getMetaAndCheck(folder string) *metadataTracker { var fixed int fixed, err = db.repairSequenceGCLocked(folder, meta) if fixed != 0 { - l.Infoln("Repaired %v sequence entries in database", fixed) + l.Infof("Repaired %d sequence entries in database", fixed) } } @@ -790,7 +790,7 @@ func (db *Lowlevel) repairSequenceGCLocked(folderStr string, meta *metadataTrack if err := t.Put(sk, it.Key()); err != nil { return 0, err } - if err := t.putFile(it.Key(), fi.copyToFileInfo()); err != nil { + if err := t.putFile(it.Key(), fi.copyToFileInfo(), true); err != nil { return 0, err } } diff --git a/lib/db/schemaupdater.go b/lib/db/schemaupdater.go index 540c1bb62..541106520 100644 --- a/lib/db/schemaupdater.go +++ b/lib/db/schemaupdater.go @@ -465,7 +465,7 @@ func (db *schemaUpdater) updateSchemato9(prev int) error { if fi.Blocks == nil { continue } - if err := t.putFile(it.Key(), fi); err != nil { + if err := t.putFile(it.Key(), fi, false); err != nil { return err } if err := t.Checkpoint(); err != nil { diff --git a/lib/db/transactions.go b/lib/db/transactions.go index c417fe84d..234d548f6 100644 --- a/lib/db/transactions.go +++ b/lib/db/transactions.go @@ -432,13 +432,19 @@ func (t readWriteTransaction) close() { t.WriteTransaction.Release() } -func (t readWriteTransaction) putFile(fkey []byte, fi protocol.FileInfo) error { +// putFile stores a file in the database, taking care of indirected fields. +// Set the truncated flag when putting a file that deliberatly can have an +// empty block list but a non-empty block list hash. This should normally be +// false. +func (t readWriteTransaction) putFile(fkey []byte, fi protocol.FileInfo, truncated bool) error { var bkey []byte - // Always set the blocks hash when there are blocks. + // Always set the blocks hash when there are blocks. Leave the blocks + // hash alone when there are no blocks and we might be putting a + // "truncated" FileInfo (no blocks, but the hash reference is live). if len(fi.Blocks) > 0 { fi.BlocksHash = protocol.BlocksHash(fi.Blocks) - } else { + } else if !truncated { fi.BlocksHash = nil }