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 committed by GitHub
parent 4c5e9cf921
commit c4abe6f815
No known key found for this signature in database
GPG Key ID: 4AEE18F83AFDEB23
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
}