123456789101112131415161718192021222324252627282930313233343536373839404142434445464748495051525354555657585960616263646566676869707172737475767778798081828384858687888990919293949596979899100101102103104105106107108109110111112113114115116117118119120121122123124125126127128129130131132133134135136137138139140141142143144145146147148149150151152153154155156157158159160161162163164165166167168169170171172173174175176177178179180181182 |
- // Copyright (C) 2015 The Syncthing Authors.
- //
- // 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,
- // You can obtain one at https://mozilla.org/MPL/2.0/.
- package model
- import (
- "time"
- "github.com/syncthing/syncthing/lib/events"
- "github.com/syncthing/syncthing/lib/sync"
- )
- type folderState int
- const (
- FolderIdle folderState = iota
- FolderScanning
- FolderScanWaiting
- FolderSyncWaiting
- FolderSyncPreparing
- FolderSyncing
- FolderCleaning
- FolderCleanWaiting
- FolderError
- )
- func (s folderState) String() string {
- switch s {
- case FolderIdle:
- return "idle"
- case FolderScanning:
- return "scanning"
- case FolderScanWaiting:
- return "scan-waiting"
- case FolderSyncWaiting:
- return "sync-waiting"
- case FolderSyncPreparing:
- return "sync-preparing"
- case FolderSyncing:
- return "syncing"
- case FolderCleaning:
- return "cleaning"
- case FolderCleanWaiting:
- return "clean-waiting"
- case FolderError:
- return "error"
- default:
- return "unknown"
- }
- }
- type remoteFolderState int
- const (
- remoteFolderUnknown remoteFolderState = iota
- remoteFolderNotSharing
- remoteFolderPaused
- remoteFolderValid
- )
- 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
- }
- type stateTracker struct {
- folderID string
- evLogger events.Logger
- mut sync.Mutex
- current folderState
- err error
- changed time.Time
- }
- func newStateTracker(id string, evLogger events.Logger) stateTracker {
- return stateTracker{
- folderID: id,
- evLogger: evLogger,
- mut: sync.NewMutex(),
- }
- }
- // setState sets the new folder state, for states other than FolderError.
- func (s *stateTracker) setState(newState folderState) {
- if newState == FolderError {
- panic("must use setError")
- }
- s.mut.Lock()
- defer s.mut.Unlock()
- if newState == s.current {
- return
- }
- defer func() {
- metricFolderState.WithLabelValues(s.folderID).Set(float64(s.current))
- }()
- /* 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
- s.changed = time.Now().Truncate(time.Second)
- s.evLogger.Log(events.StateChanged, eventData)
- }
- // 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) {
- s.mut.Lock()
- current, changed, err = s.current, s.changed, s.err
- s.mut.Unlock()
- return
- }
- // setError sets the folder state to FolderError with the specified error or
- // to FolderIdle if the error is nil
- func (s *stateTracker) setError(err error) {
- s.mut.Lock()
- defer s.mut.Unlock()
- defer func() {
- metricFolderState.WithLabelValues(s.folderID).Set(float64(s.current))
- }()
- eventData := map[string]interface{}{
- "folder": s.folderID,
- "from": s.current.String(),
- }
- if err != nil {
- eventData["error"] = err.Error()
- s.current = FolderError
- } else {
- s.current = FolderIdle
- }
- eventData["to"] = s.current.String()
- if !s.changed.IsZero() {
- eventData["duration"] = time.Since(s.changed).Seconds()
- }
- s.err = err
- s.changed = time.Now().Truncate(time.Second)
- s.evLogger.Log(events.StateChanged, eventData)
- }
|