From 070bf3b776a59f94f6dd9eb341da2edde6d84265 Mon Sep 17 00:00:00 2001 From: Simon Frei Date: Thu, 4 Feb 2021 14:42:46 +0100 Subject: [PATCH] lib/db: Report number of repaired items from checkGlobal (#7329) --- lib/db/db_test.go | 4 +++- lib/db/lowlevel.go | 31 ++++++++++++++++++------------- 2 files changed, 21 insertions(+), 14 deletions(-) diff --git a/lib/db/db_test.go b/lib/db/db_test.go index 749185c5b..8873fba65 100644 --- a/lib/db/db_test.go +++ b/lib/db/db_test.go @@ -513,8 +513,10 @@ func TestCheckGlobals(t *testing.T) { } // Clean up global entry of the now missing file - if err := db.checkGlobals([]byte(fs.folder)); err != nil { + if repaired, err := db.checkGlobals([]byte(fs.folder)); err != nil { t.Fatal(err) + } else if repaired != 1 { + t.Error("Expected 1 repaired global item, got", repaired) } // Check that the global entry is gone diff --git a/lib/db/lowlevel.go b/lib/db/lowlevel.go index 6dda13e82..d384194bb 100644 --- a/lib/db/lowlevel.go +++ b/lib/db/lowlevel.go @@ -441,30 +441,31 @@ func (db *Lowlevel) dropDeviceFolder(device, folder []byte, meta *metadataTracke return t.Commit() } -func (db *Lowlevel) checkGlobals(folder []byte) error { +func (db *Lowlevel) checkGlobals(folder []byte) (int, error) { t, err := db.newReadWriteTransaction() if err != nil { - return err + return 0, err } defer t.close() key, err := db.keyer.GenerateGlobalVersionKey(nil, folder, nil) if err != nil { - return err + return 0, err } dbi, err := t.NewPrefixIterator(key.WithoutName()) if err != nil { - return err + return 0, err } defer dbi.Release() + fixed := 0 var dk []byte ro := t.readOnlyTransaction for dbi.Next() { var vl VersionList if err := vl.Unmarshal(dbi.Value()); err != nil || vl.Empty() { if err := t.Delete(dbi.Key()); err != nil && !backend.IsNotFound(err) { - return err + return 0, err } continue } @@ -480,34 +481,36 @@ func (db *Lowlevel) checkGlobals(folder []byte) error { for _, fv := range vl.RawVersions { changedHere, err = checkGlobalsFilterDevices(dk, folder, name, fv.Devices, newVL, ro) if err != nil { - return err + return 0, err } changed = changed || changedHere changedHere, err = checkGlobalsFilterDevices(dk, folder, name, fv.InvalidDevices, newVL, ro) if err != nil { - return err + return 0, err } changed = changed || changedHere } if newVL.Empty() { if err := t.Delete(dbi.Key()); err != nil && !backend.IsNotFound(err) { - return err + return 0, err } + fixed++ } else if changed { if err := t.Put(dbi.Key(), mustMarshal(newVL)); err != nil { - return err + return 0, err } + fixed++ } } dbi.Release() if err := dbi.Error(); err != nil { - return err + return 0, err } - l.Debugf("db check completed for %q", folder) - return t.Commit() + l.Debugf("global db check completed for %q", folder) + return fixed, t.Commit() } func checkGlobalsFilterDevices(dk, folder, name []byte, devices [][]byte, vl *VersionList, t readOnlyTransaction) (bool, error) { @@ -899,8 +902,10 @@ func (db *Lowlevel) recalcMeta(folderStr string) (*metadataTracker, error) { folder := []byte(folderStr) meta := newMetadataTracker(db.keyer, db.evLogger) - if err := db.checkGlobals(folder); err != nil { + if fixed, err := db.checkGlobals(folder); err != nil { return nil, fmt.Errorf("checking globals: %w", err) + } else if fixed > 0 { + l.Infof("Repaired %d global entries for folder %v in database", fixed, folderStr) } t, err := db.newReadWriteTransaction(meta.CommitHook(folder))