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...
This commit is contained in:
Jakob Borg 2020-03-20 12:07:14 +01:00
parent b33d5e57c6
commit f1b253fc00
4 changed files with 25 additions and 15 deletions

View File

@ -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)

View File

@ -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
}
}

View File

@ -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 {

View File

@ -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
}