2015-03-16 20:14:19 +00:00
|
|
|
// Copyright (C) 2015 The Syncthing Authors.
|
|
|
|
//
|
2015-04-12 20:12:01 +00:00
|
|
|
// This Source Code Form is subject to the terms of the Mozilla Public
|
|
|
|
// License, v. 2.0. If a copy of the MPL was not distributed with this file,
|
2017-02-09 06:52:18 +00:00
|
|
|
// You can obtain one at https://mozilla.org/MPL/2.0/.
|
2015-03-16 20:14:19 +00:00
|
|
|
|
|
|
|
package model
|
|
|
|
|
|
|
|
import (
|
|
|
|
"time"
|
|
|
|
|
2015-08-06 09:29:25 +00:00
|
|
|
"github.com/syncthing/syncthing/lib/events"
|
|
|
|
"github.com/syncthing/syncthing/lib/sync"
|
2015-03-16 20:14:19 +00:00
|
|
|
)
|
|
|
|
|
|
|
|
type folderState int
|
|
|
|
|
|
|
|
const (
|
|
|
|
FolderIdle folderState = iota
|
|
|
|
FolderScanning
|
2018-12-05 07:40:05 +00:00
|
|
|
FolderScanWaiting
|
2020-01-27 16:31:17 +00:00
|
|
|
FolderSyncWaiting
|
2019-10-16 07:08:54 +00:00
|
|
|
FolderSyncPreparing
|
2015-03-16 20:14:19 +00:00
|
|
|
FolderSyncing
|
2020-07-14 08:48:50 +00:00
|
|
|
FolderCleaning
|
|
|
|
FolderCleanWaiting
|
2015-04-12 20:12:01 +00:00
|
|
|
FolderError
|
2015-03-16 20:14:19 +00:00
|
|
|
)
|
|
|
|
|
|
|
|
func (s folderState) String() string {
|
|
|
|
switch s {
|
|
|
|
case FolderIdle:
|
|
|
|
return "idle"
|
|
|
|
case FolderScanning:
|
|
|
|
return "scanning"
|
2018-12-05 07:40:05 +00:00
|
|
|
case FolderScanWaiting:
|
|
|
|
return "scan-waiting"
|
2020-01-27 16:31:17 +00:00
|
|
|
case FolderSyncWaiting:
|
|
|
|
return "sync-waiting"
|
2019-10-16 07:08:54 +00:00
|
|
|
case FolderSyncPreparing:
|
|
|
|
return "sync-preparing"
|
2015-03-16 20:14:19 +00:00
|
|
|
case FolderSyncing:
|
|
|
|
return "syncing"
|
2020-07-14 08:48:50 +00:00
|
|
|
case FolderCleaning:
|
|
|
|
return "cleaning"
|
|
|
|
case FolderCleanWaiting:
|
|
|
|
return "clean-waiting"
|
2015-04-12 20:12:01 +00:00
|
|
|
case FolderError:
|
|
|
|
return "error"
|
2015-03-16 20:14:19 +00:00
|
|
|
default:
|
|
|
|
return "unknown"
|
|
|
|
}
|
|
|
|
}
|
|
|
|
|
2022-04-10 20:47:57 +00:00
|
|
|
type remoteFolderState int
|
|
|
|
|
|
|
|
const (
|
2022-04-22 06:42:20 +00:00
|
|
|
remoteFolderUnknown remoteFolderState = iota
|
|
|
|
remoteFolderNotSharing
|
|
|
|
remoteFolderPaused
|
|
|
|
remoteFolderValid
|
2022-04-10 20:47:57 +00:00
|
|
|
)
|
|
|
|
|
2022-04-22 06:42:20 +00:00
|
|
|
func (s remoteFolderState) String() string {
|
|
|
|
switch s {
|
|
|
|
case remoteFolderUnknown:
|
|
|
|
return "unknown"
|
|
|
|
case remoteFolderNotSharing:
|
|
|
|
return "notSharing"
|
|
|
|
case remoteFolderPaused:
|
|
|
|
return "paused"
|
|
|
|
case remoteFolderValid:
|
|
|
|
return "valid"
|
|
|
|
default:
|
|
|
|
return "unknown"
|
|
|
|
}
|
|
|
|
}
|
|
|
|
|
|
|
|
func (s remoteFolderState) MarshalText() ([]byte, error) {
|
|
|
|
return []byte(s.String()), nil
|
|
|
|
}
|
|
|
|
|
2015-03-16 20:14:19 +00:00
|
|
|
type stateTracker struct {
|
2016-04-26 14:01:46 +00:00
|
|
|
folderID string
|
2019-08-15 14:29:37 +00:00
|
|
|
evLogger events.Logger
|
2015-03-16 20:14:19 +00:00
|
|
|
|
|
|
|
mut sync.Mutex
|
|
|
|
current folderState
|
2015-04-12 20:12:01 +00:00
|
|
|
err error
|
2015-03-16 20:14:19 +00:00
|
|
|
changed time.Time
|
|
|
|
}
|
|
|
|
|
2019-08-15 14:29:37 +00:00
|
|
|
func newStateTracker(id string, evLogger events.Logger) stateTracker {
|
2016-06-29 06:37:34 +00:00
|
|
|
return stateTracker{
|
|
|
|
folderID: id,
|
2019-08-15 14:29:37 +00:00
|
|
|
evLogger: evLogger,
|
2016-06-29 06:37:34 +00:00
|
|
|
mut: sync.NewMutex(),
|
|
|
|
}
|
|
|
|
}
|
|
|
|
|
2015-04-12 20:12:01 +00:00
|
|
|
// setState sets the new folder state, for states other than FolderError.
|
2015-03-16 20:14:19 +00:00
|
|
|
func (s *stateTracker) setState(newState folderState) {
|
2015-04-12 20:12:01 +00:00
|
|
|
if newState == FolderError {
|
|
|
|
panic("must use setError")
|
|
|
|
}
|
|
|
|
|
2015-03-16 20:14:19 +00:00
|
|
|
s.mut.Lock()
|
2019-10-16 07:08:54 +00:00
|
|
|
defer s.mut.Unlock()
|
|
|
|
|
|
|
|
if newState == s.current {
|
|
|
|
return
|
2015-03-16 20:14:19 +00:00
|
|
|
}
|
2019-10-16 07:08:54 +00:00
|
|
|
|
2023-08-04 17:57:30 +00:00
|
|
|
defer func() {
|
|
|
|
metricFolderState.WithLabelValues(s.folderID).Set(float64(s.current))
|
|
|
|
}()
|
|
|
|
|
2019-10-16 07:08:54 +00:00
|
|
|
/* This should hold later...
|
|
|
|
if s.current != FolderIdle && (newState == FolderScanning || newState == FolderSyncing) {
|
|
|
|
panic("illegal state transition " + s.current.String() + " -> " + newState.String())
|
|
|
|
}
|
|
|
|
*/
|
|
|
|
|
|
|
|
eventData := map[string]interface{}{
|
|
|
|
"folder": s.folderID,
|
|
|
|
"to": newState.String(),
|
|
|
|
"from": s.current.String(),
|
|
|
|
}
|
|
|
|
|
|
|
|
if !s.changed.IsZero() {
|
|
|
|
eventData["duration"] = time.Since(s.changed).Seconds()
|
|
|
|
}
|
|
|
|
|
|
|
|
s.current = newState
|
2021-03-12 09:35:10 +00:00
|
|
|
s.changed = time.Now().Truncate(time.Second)
|
2019-10-16 07:08:54 +00:00
|
|
|
|
|
|
|
s.evLogger.Log(events.StateChanged, eventData)
|
2015-03-16 20:14:19 +00:00
|
|
|
}
|
|
|
|
|
2015-04-12 20:12:01 +00:00
|
|
|
// getState returns the current state, the time when it last changed, and the
|
|
|
|
// current error or nil.
|
|
|
|
func (s *stateTracker) getState() (current folderState, changed time.Time, err error) {
|
2015-03-16 20:14:19 +00:00
|
|
|
s.mut.Lock()
|
2015-04-12 20:12:01 +00:00
|
|
|
current, changed, err = s.current, s.changed, s.err
|
2015-03-16 20:14:19 +00:00
|
|
|
s.mut.Unlock()
|
|
|
|
return
|
|
|
|
}
|
2015-04-12 20:12:01 +00:00
|
|
|
|
2017-10-24 07:58:55 +00:00
|
|
|
// setError sets the folder state to FolderError with the specified error or
|
|
|
|
// to FolderIdle if the error is nil
|
2015-04-12 20:12:01 +00:00
|
|
|
func (s *stateTracker) setError(err error) {
|
|
|
|
s.mut.Lock()
|
2017-10-24 07:58:55 +00:00
|
|
|
defer s.mut.Unlock()
|
2015-04-12 20:12:01 +00:00
|
|
|
|
2023-08-04 17:57:30 +00:00
|
|
|
defer func() {
|
|
|
|
metricFolderState.WithLabelValues(s.folderID).Set(float64(s.current))
|
|
|
|
}()
|
|
|
|
|
2017-10-24 07:58:55 +00:00
|
|
|
eventData := map[string]interface{}{
|
|
|
|
"folder": s.folderID,
|
|
|
|
"from": s.current.String(),
|
|
|
|
}
|
2015-04-12 20:12:01 +00:00
|
|
|
|
2017-10-24 07:58:55 +00:00
|
|
|
if err != nil {
|
|
|
|
eventData["error"] = err.Error()
|
2015-04-12 20:12:01 +00:00
|
|
|
s.current = FolderError
|
2017-10-24 07:58:55 +00:00
|
|
|
} else {
|
|
|
|
s.current = FolderIdle
|
2015-04-12 20:12:01 +00:00
|
|
|
}
|
2015-06-13 18:10:11 +00:00
|
|
|
|
2017-10-24 07:58:55 +00:00
|
|
|
eventData["to"] = s.current.String()
|
2015-06-13 18:10:11 +00:00
|
|
|
|
2017-10-24 07:58:55 +00:00
|
|
|
if !s.changed.IsZero() {
|
|
|
|
eventData["duration"] = time.Since(s.changed).Seconds()
|
|
|
|
}
|
2015-06-13 18:10:11 +00:00
|
|
|
|
2017-10-24 07:58:55 +00:00
|
|
|
s.err = err
|
2021-03-12 09:35:10 +00:00
|
|
|
s.changed = time.Now().Truncate(time.Second)
|
2015-06-13 18:10:11 +00:00
|
|
|
|
2019-08-15 14:29:37 +00:00
|
|
|
s.evLogger.Log(events.StateChanged, eventData)
|
2015-06-13 18:10:11 +00:00
|
|
|
}
|