From 424d1b16082233b0cb1da2ad478ae8ac3d9bd428 Mon Sep 17 00:00:00 2001 From: Simon Frei Date: Tue, 28 Jul 2020 16:46:42 +0200 Subject: [PATCH] lib/db: Commit meta when dropping device (#6862) --- lib/db/backend/backend.go | 14 ++++++++------ lib/db/lowlevel.go | 21 ++++++++++----------- 2 files changed, 18 insertions(+), 17 deletions(-) diff --git a/lib/db/backend/backend.go b/lib/db/backend/backend.go index 234173402..fa185d713 100644 --- a/lib/db/backend/backend.go +++ b/lib/db/backend/backend.go @@ -15,6 +15,9 @@ import ( "github.com/syncthing/syncthing/lib/locations" ) +// CommitHook is a function that is executed before a WriteTransaction is +// committed or before it is flushed to disk, e.g. on calling CheckPoint. The +// transaction can be accessed via a closure. type CommitHook func(WriteTransaction) error // The Reader interface specifies the read-only operations available on the @@ -54,12 +57,11 @@ type ReadTransaction interface { // A Checkpoint is a potential partial commit of the transaction so far, for // purposes of saving memory when transactions are in-RAM. Note that // transactions may be checkpointed *anyway* even if this is not called, due to -// resource constraints, but this gives you a chance to decide when. -// -// Functions can be passed to Checkpoint. These are run if and only if the -// checkpoint will result in a flush, and will run before the flush. The -// transaction can be accessed via a closure. If an error is returned from -// these functions the flush will be aborted and the error bubbled. +// resource constraints, but this gives you a chance to decide when. If, and +// only if, calling Checkpoint will result in a partial commit/flush, the +// CommitHooks passed to Backend.NewWriteTransaction are called before +// committing. If any of those returns an error, committing is aborted and the +// error bubbled. type WriteTransaction interface { ReadTransaction Writer diff --git a/lib/db/lowlevel.go b/lib/db/lowlevel.go index 27c0efa3a..e2e6acc33 100644 --- a/lib/db/lowlevel.go +++ b/lib/db/lowlevel.go @@ -362,7 +362,7 @@ func (db *Lowlevel) dropDeviceFolder(device, folder []byte, meta *metadataTracke db.gcMut.RLock() defer db.gcMut.RUnlock() - t, err := db.newReadWriteTransaction() + t, err := db.newReadWriteTransaction(meta.CommitHook(folder)) if err != nil { return err } @@ -843,20 +843,22 @@ func (db *Lowlevel) loadMetadataTracker(folder string) *metadataTracker { return meta } -func (db *Lowlevel) recalcMeta(folder string) (*metadataTracker, error) { +func (db *Lowlevel) recalcMeta(folderStr string) (*metadataTracker, error) { + folder := []byte(folderStr) + meta := newMetadataTracker(db.keyer) - if err := db.checkGlobals([]byte(folder)); err != nil { + if err := db.checkGlobals(folder); err != nil { return nil, err } - t, err := db.newReadWriteTransaction() + t, err := db.newReadWriteTransaction(meta.CommitHook(folder)) if err != nil { return nil, err } defer t.close() var deviceID protocol.DeviceID - err = t.withAllFolderTruncated([]byte(folder), func(device []byte, f FileInfoTruncated) bool { + err = t.withAllFolderTruncated(folder, func(device []byte, f FileInfoTruncated) bool { copy(deviceID[:], device) meta.addFile(deviceID, f) return true @@ -865,13 +867,13 @@ func (db *Lowlevel) recalcMeta(folder string) (*metadataTracker, error) { return nil, err } - err = t.withGlobal([]byte(folder), nil, true, func(f protocol.FileIntf) bool { + err = t.withGlobal(folder, nil, true, func(f protocol.FileIntf) bool { meta.addFile(protocol.GlobalDeviceID, f) return true }) meta.emptyNeeded(protocol.LocalDeviceID) - err = t.withNeed([]byte(folder), protocol.LocalDeviceID[:], true, func(f protocol.FileIntf) bool { + err = t.withNeed(folder, protocol.LocalDeviceID[:], true, func(f protocol.FileIntf) bool { meta.addNeeded(protocol.LocalDeviceID, f) return true }) @@ -880,7 +882,7 @@ func (db *Lowlevel) recalcMeta(folder string) (*metadataTracker, error) { } for _, device := range meta.devices() { meta.emptyNeeded(device) - err = t.withNeed([]byte(folder), device[:], true, func(f protocol.FileIntf) bool { + err = t.withNeed(folder, device[:], true, func(f protocol.FileIntf) bool { meta.addNeeded(device, f) return true }) @@ -890,9 +892,6 @@ func (db *Lowlevel) recalcMeta(folder string) (*metadataTracker, error) { } meta.SetCreated() - if err := meta.toDB(t, []byte(folder)); err != nil { - return nil, err - } if err := t.Commit(); err != nil { return nil, err }