mirror of
https://github.com/octoleo/syncthing.git
synced 2024-11-17 18:45:13 +00:00
chore(model): improve tracking sentPrevSeq for index debugging (#9740)
This commit is contained in:
parent
fb939ec496
commit
19f63c7ea3
@ -25,9 +25,24 @@ type indexHandler struct {
|
|||||||
downloads *deviceDownloadState
|
downloads *deviceDownloadState
|
||||||
folder string
|
folder string
|
||||||
folderIsReceiveEncrypted bool
|
folderIsReceiveEncrypted bool
|
||||||
prevSequence int64
|
|
||||||
evLogger events.Logger
|
evLogger events.Logger
|
||||||
|
|
||||||
|
// We track the latest / highest sequence number in two ways for two
|
||||||
|
// different reasons. Initially they are the same -- the highest seen
|
||||||
|
// sequence number reported by the other side (or zero).
|
||||||
|
//
|
||||||
|
// One is the highest number we've seen when iterating the database,
|
||||||
|
// which we track for database iteration purposes. When we loop, we
|
||||||
|
// start looking at that number plus one in the next loop. Our index
|
||||||
|
// numbering may have holes which this will skip over.
|
||||||
|
//
|
||||||
|
// The other is the highest sequence we previously sent to the other
|
||||||
|
// side, used by them for correctness checks. This one must not skip
|
||||||
|
// holes. That is, if we iterate and find a hole, this is not
|
||||||
|
// incremented because nothing was sent to the other side.
|
||||||
|
localPrevSequence int64 // the highest sequence number we've seen in our FileInfos
|
||||||
|
sentPrevSequence int64 // the highest sequence number we've sent to the peer
|
||||||
|
|
||||||
cond *sync.Cond
|
cond *sync.Cond
|
||||||
paused bool
|
paused bool
|
||||||
fset *db.FileSet
|
fset *db.FileSet
|
||||||
@ -100,7 +115,8 @@ func newIndexHandler(conn protocol.Connection, downloads *deviceDownloadState, f
|
|||||||
downloads: downloads,
|
downloads: downloads,
|
||||||
folder: folder.ID,
|
folder: folder.ID,
|
||||||
folderIsReceiveEncrypted: folder.Type == config.FolderTypeReceiveEncrypted,
|
folderIsReceiveEncrypted: folder.Type == config.FolderTypeReceiveEncrypted,
|
||||||
prevSequence: startSequence,
|
localPrevSequence: startSequence,
|
||||||
|
sentPrevSequence: startSequence,
|
||||||
evLogger: evLogger,
|
evLogger: evLogger,
|
||||||
|
|
||||||
fset: fset,
|
fset: fset,
|
||||||
@ -127,7 +143,7 @@ func (s *indexHandler) waitForFileset(ctx context.Context) (*db.FileSet, error)
|
|||||||
}
|
}
|
||||||
|
|
||||||
func (s *indexHandler) Serve(ctx context.Context) (err error) {
|
func (s *indexHandler) Serve(ctx context.Context) (err error) {
|
||||||
l.Debugf("Starting index handler for %s to %s at %s (slv=%d)", s.folder, s.conn.DeviceID().Short(), s.conn, s.prevSequence)
|
l.Debugf("Starting index handler for %s to %s at %s (localPrevSequence=%d)", s.folder, s.conn.DeviceID().Short(), s.conn, s.localPrevSequence)
|
||||||
stop := make(chan struct{})
|
stop := make(chan struct{})
|
||||||
|
|
||||||
defer func() {
|
defer func() {
|
||||||
@ -172,7 +188,7 @@ func (s *indexHandler) Serve(ctx context.Context) (err error) {
|
|||||||
// currently in the database, wait for the local index to update. The
|
// currently in the database, wait for the local index to update. The
|
||||||
// local index may update for other folders than the one we are
|
// local index may update for other folders than the one we are
|
||||||
// sending for.
|
// sending for.
|
||||||
if fset.Sequence(protocol.LocalDeviceID) <= s.prevSequence {
|
if fset.Sequence(protocol.LocalDeviceID) <= s.localPrevSequence {
|
||||||
select {
|
select {
|
||||||
case <-ctx.Done():
|
case <-ctx.Done():
|
||||||
return ctx.Err()
|
return ctx.Err()
|
||||||
@ -223,13 +239,7 @@ func (s *indexHandler) pause() {
|
|||||||
// sendIndexTo sends file infos with a sequence number higher than prevSequence and
|
// sendIndexTo sends file infos with a sequence number higher than prevSequence and
|
||||||
// returns the highest sent sequence number.
|
// returns the highest sent sequence number.
|
||||||
func (s *indexHandler) sendIndexTo(ctx context.Context, fset *db.FileSet) error {
|
func (s *indexHandler) sendIndexTo(ctx context.Context, fset *db.FileSet) error {
|
||||||
// Keep track of the previous sequence we sent. This is separate from
|
initial := s.localPrevSequence == 0
|
||||||
// s.prevSequence because the latter will skip over holes in the
|
|
||||||
// sequence numberings, while sentPrevSequence should always be
|
|
||||||
// precisely the highest previously sent sequence.
|
|
||||||
sentPrevSequence := s.prevSequence
|
|
||||||
|
|
||||||
initial := s.prevSequence == 0
|
|
||||||
batch := db.NewFileInfoBatch(nil)
|
batch := db.NewFileInfoBatch(nil)
|
||||||
var batchError error
|
var batchError error
|
||||||
batch.SetFlushFunc(func(fs []protocol.FileInfo) error {
|
batch.SetFlushFunc(func(fs []protocol.FileInfo) error {
|
||||||
@ -262,7 +272,7 @@ func (s *indexHandler) sendIndexTo(ctx context.Context, fset *db.FileSet) error
|
|||||||
err = s.conn.IndexUpdate(ctx, &protocol.IndexUpdate{
|
err = s.conn.IndexUpdate(ctx, &protocol.IndexUpdate{
|
||||||
Folder: s.folder,
|
Folder: s.folder,
|
||||||
Files: fs,
|
Files: fs,
|
||||||
PrevSequence: sentPrevSequence,
|
PrevSequence: s.sentPrevSequence,
|
||||||
LastSequence: lastSequence,
|
LastSequence: lastSequence,
|
||||||
})
|
})
|
||||||
}
|
}
|
||||||
@ -270,7 +280,7 @@ func (s *indexHandler) sendIndexTo(ctx context.Context, fset *db.FileSet) error
|
|||||||
batchError = err
|
batchError = err
|
||||||
return err
|
return err
|
||||||
}
|
}
|
||||||
sentPrevSequence = lastSequence
|
s.sentPrevSequence = lastSequence
|
||||||
return nil
|
return nil
|
||||||
})
|
})
|
||||||
|
|
||||||
@ -282,7 +292,7 @@ func (s *indexHandler) sendIndexTo(ctx context.Context, fset *db.FileSet) error
|
|||||||
}
|
}
|
||||||
defer snap.Release()
|
defer snap.Release()
|
||||||
previousWasDelete := false
|
previousWasDelete := false
|
||||||
snap.WithHaveSequence(s.prevSequence+1, func(fi protocol.FileIntf) bool {
|
snap.WithHaveSequence(s.localPrevSequence+1, func(fi protocol.FileIntf) bool {
|
||||||
// This is to make sure that renames (which is an add followed by a delete) land in the same batch.
|
// This is to make sure that renames (which is an add followed by a delete) land in the same batch.
|
||||||
// Even if the batch is full, we allow a last delete to slip in, we do this by making sure that
|
// Even if the batch is full, we allow a last delete to slip in, we do this by making sure that
|
||||||
// the batch ends with a non-delete, or that the last item in the batch is already a delete
|
// the batch ends with a non-delete, or that the last item in the batch is already a delete
|
||||||
@ -292,17 +302,17 @@ func (s *indexHandler) sendIndexTo(ctx context.Context, fset *db.FileSet) error
|
|||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
if fi.SequenceNo() < s.prevSequence+1 {
|
if fi.SequenceNo() < s.localPrevSequence+1 {
|
||||||
s.logSequenceAnomaly("database returned sequence lower than requested", map[string]any{
|
s.logSequenceAnomaly("database returned sequence lower than requested", map[string]any{
|
||||||
"sequence": fi.SequenceNo(),
|
"sequence": fi.SequenceNo(),
|
||||||
"start": s.prevSequence + 1,
|
"start": s.localPrevSequence + 1,
|
||||||
})
|
})
|
||||||
}
|
}
|
||||||
|
|
||||||
if f.Sequence > 0 && fi.SequenceNo() <= f.Sequence {
|
if f.Sequence > 0 && fi.SequenceNo() <= f.Sequence {
|
||||||
s.logSequenceAnomaly("database returned non-increasing sequence", map[string]any{
|
s.logSequenceAnomaly("database returned non-increasing sequence", map[string]any{
|
||||||
"sequence": fi.SequenceNo(),
|
"sequence": fi.SequenceNo(),
|
||||||
"start": s.prevSequence + 1,
|
"start": s.localPrevSequence + 1,
|
||||||
"previous": f.Sequence,
|
"previous": f.Sequence,
|
||||||
})
|
})
|
||||||
// Abort this round of index sending - the next one will pick
|
// Abort this round of index sending - the next one will pick
|
||||||
@ -348,7 +358,7 @@ func (s *indexHandler) sendIndexTo(ctx context.Context, fset *db.FileSet) error
|
|||||||
// however it's possible that a higher sequence exists, just doesn't need to
|
// however it's possible that a higher sequence exists, just doesn't need to
|
||||||
// be sent (e.g. in a receive-only folder, when a local change was
|
// be sent (e.g. in a receive-only folder, when a local change was
|
||||||
// reverted). No point trying to send nothing again.
|
// reverted). No point trying to send nothing again.
|
||||||
s.prevSequence = snap.Sequence(protocol.LocalDeviceID)
|
s.localPrevSequence = snap.Sequence(protocol.LocalDeviceID)
|
||||||
|
|
||||||
return nil
|
return nil
|
||||||
}
|
}
|
||||||
|
Loading…
Reference in New Issue
Block a user