lib/db: Commit meta when dropping device (#6862)
This commit is contained in:
@@ -15,6 +15,9 @@ import (
|
|||||||
"github.com/syncthing/syncthing/lib/locations"
|
"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
|
type CommitHook func(WriteTransaction) error
|
||||||
|
|
||||||
// The Reader interface specifies the read-only operations available on the
|
// 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
|
// A Checkpoint is a potential partial commit of the transaction so far, for
|
||||||
// purposes of saving memory when transactions are in-RAM. Note that
|
// purposes of saving memory when transactions are in-RAM. Note that
|
||||||
// transactions may be checkpointed *anyway* even if this is not called, due to
|
// transactions may be checkpointed *anyway* even if this is not called, due to
|
||||||
// resource constraints, but this gives you a chance to decide when.
|
// 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
|
||||||
// Functions can be passed to Checkpoint. These are run if and only if the
|
// CommitHooks passed to Backend.NewWriteTransaction are called before
|
||||||
// checkpoint will result in a flush, and will run before the flush. The
|
// committing. If any of those returns an error, committing is aborted and the
|
||||||
// transaction can be accessed via a closure. If an error is returned from
|
// error bubbled.
|
||||||
// these functions the flush will be aborted and the error bubbled.
|
|
||||||
type WriteTransaction interface {
|
type WriteTransaction interface {
|
||||||
ReadTransaction
|
ReadTransaction
|
||||||
Writer
|
Writer
|
||||||
|
|||||||
+10
-11
@@ -362,7 +362,7 @@ func (db *Lowlevel) dropDeviceFolder(device, folder []byte, meta *metadataTracke
|
|||||||
db.gcMut.RLock()
|
db.gcMut.RLock()
|
||||||
defer db.gcMut.RUnlock()
|
defer db.gcMut.RUnlock()
|
||||||
|
|
||||||
t, err := db.newReadWriteTransaction()
|
t, err := db.newReadWriteTransaction(meta.CommitHook(folder))
|
||||||
if err != nil {
|
if err != nil {
|
||||||
return err
|
return err
|
||||||
}
|
}
|
||||||
@@ -843,20 +843,22 @@ func (db *Lowlevel) loadMetadataTracker(folder string) *metadataTracker {
|
|||||||
return meta
|
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)
|
meta := newMetadataTracker(db.keyer)
|
||||||
if err := db.checkGlobals([]byte(folder)); err != nil {
|
if err := db.checkGlobals(folder); err != nil {
|
||||||
return nil, err
|
return nil, err
|
||||||
}
|
}
|
||||||
|
|
||||||
t, err := db.newReadWriteTransaction()
|
t, err := db.newReadWriteTransaction(meta.CommitHook(folder))
|
||||||
if err != nil {
|
if err != nil {
|
||||||
return nil, err
|
return nil, err
|
||||||
}
|
}
|
||||||
defer t.close()
|
defer t.close()
|
||||||
|
|
||||||
var deviceID protocol.DeviceID
|
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)
|
copy(deviceID[:], device)
|
||||||
meta.addFile(deviceID, f)
|
meta.addFile(deviceID, f)
|
||||||
return true
|
return true
|
||||||
@@ -865,13 +867,13 @@ func (db *Lowlevel) recalcMeta(folder string) (*metadataTracker, error) {
|
|||||||
return nil, err
|
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)
|
meta.addFile(protocol.GlobalDeviceID, f)
|
||||||
return true
|
return true
|
||||||
})
|
})
|
||||||
|
|
||||||
meta.emptyNeeded(protocol.LocalDeviceID)
|
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)
|
meta.addNeeded(protocol.LocalDeviceID, f)
|
||||||
return true
|
return true
|
||||||
})
|
})
|
||||||
@@ -880,7 +882,7 @@ func (db *Lowlevel) recalcMeta(folder string) (*metadataTracker, error) {
|
|||||||
}
|
}
|
||||||
for _, device := range meta.devices() {
|
for _, device := range meta.devices() {
|
||||||
meta.emptyNeeded(device)
|
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)
|
meta.addNeeded(device, f)
|
||||||
return true
|
return true
|
||||||
})
|
})
|
||||||
@@ -890,9 +892,6 @@ func (db *Lowlevel) recalcMeta(folder string) (*metadataTracker, error) {
|
|||||||
}
|
}
|
||||||
|
|
||||||
meta.SetCreated()
|
meta.SetCreated()
|
||||||
if err := meta.toDB(t, []byte(folder)); err != nil {
|
|
||||||
return nil, err
|
|
||||||
}
|
|
||||||
if err := t.Commit(); err != nil {
|
if err := t.Commit(); err != nil {
|
||||||
return nil, err
|
return nil, err
|
||||||
}
|
}
|
||||||
|
|||||||
Reference in New Issue
Block a user