Restructure modules (#1572)
* Move portbase into monorepo * Add new simple module mgr * [WIP] Switch to new simple module mgr * Add StateMgr and more worker variants * [WIP] Switch more modules * [WIP] Switch more modules * [WIP] swtich more modules * [WIP] switch all SPN modules * [WIP] switch all service modules * [WIP] Convert all workers to the new module system * [WIP] add new task system to module manager * [WIP] Add second take for scheduling workers * [WIP] Add FIXME for bugs in new scheduler * [WIP] Add minor improvements to scheduler * [WIP] Add new worker scheduler * [WIP] Fix more bug related to new module system * [WIP] Fix start handing of the new module system * [WIP] Improve startup process * [WIP] Fix minor issues * [WIP] Fix missing subsystem in settings * [WIP] Initialize managers in constructor * [WIP] Move module event initialization to constrictors * [WIP] Fix setting for enabling and disabling the SPN module * [WIP] Move API registeration into module construction * [WIP] Update states mgr for all modules * [WIP] Add CmdLine operation support * Add state helper methods to module group and instance * Add notification and module status handling to status package * Fix starting issues * Remove pilot widget and update security lock to new status data * Remove debug logs * Improve http server shutdown * Add workaround for cleanly shutting down firewall+netquery * Improve logging * Add syncing states with notifications for new module system * Improve starting, stopping, shutdown; resolve FIXMEs/TODOs * [WIP] Fix most unit tests * Review new module system and fix minor issues * Push shutdown and restart events again via API * Set sleep mode via interface * Update example/template module * [WIP] Fix spn/cabin unit test * Remove deprecated UI elements * Make log output more similar for the logging transition phase * Switch spn hub and observer cmds to new module system * Fix log sources * Make worker mgr less error prone * Fix tests and minor issues * Fix observation hub * Improve shutdown and restart handling * Split up big connection.go source file * Move varint and dsd packages to structures repo * Improve expansion test * Fix linter warnings * Fix interception module on windows * Fix linter errors --------- Co-authored-by: Vladimir Stoilov <vladimir@safing.io>
This commit is contained in:
180
base/updater/state.go
Normal file
180
base/updater/state.go
Normal file
@@ -0,0 +1,180 @@
|
||||
package updater
|
||||
|
||||
import (
|
||||
"sort"
|
||||
"sync"
|
||||
"time"
|
||||
|
||||
"github.com/safing/portmaster/base/utils"
|
||||
)
|
||||
|
||||
// Registry States.
|
||||
const (
|
||||
StateReady = "ready" // Default idle state.
|
||||
StateChecking = "checking" // Downloading indexes.
|
||||
StateDownloading = "downloading" // Downloading updates.
|
||||
StateFetching = "fetching" // Fetching a single file.
|
||||
)
|
||||
|
||||
// RegistryState describes the registry state.
|
||||
type RegistryState struct {
|
||||
sync.Mutex
|
||||
reg *ResourceRegistry
|
||||
|
||||
// ID holds the ID of the state the registry is currently in.
|
||||
ID string
|
||||
|
||||
// Details holds further information about the current state.
|
||||
Details any
|
||||
|
||||
// Updates holds generic information about the current status of pending
|
||||
// and recently downloaded updates.
|
||||
Updates UpdateState
|
||||
|
||||
// operationLock locks the operation of any state changing operation.
|
||||
// This is separate from the registry lock, which locks access to the
|
||||
// registry struct.
|
||||
operationLock sync.Mutex
|
||||
}
|
||||
|
||||
// StateDownloadingDetails holds details of the downloading state.
|
||||
type StateDownloadingDetails struct {
|
||||
// Resources holds the resource IDs that are being downloaded.
|
||||
Resources []string
|
||||
|
||||
// FinishedUpTo holds the index of Resources that is currently being
|
||||
// downloaded. Previous resources have finished downloading.
|
||||
FinishedUpTo int
|
||||
}
|
||||
|
||||
// UpdateState holds generic information about the current status of pending
|
||||
// and recently downloaded updates.
|
||||
type UpdateState struct {
|
||||
// LastCheckAt holds the time of the last update check.
|
||||
LastCheckAt *time.Time
|
||||
// LastCheckError holds the error of the last check.
|
||||
LastCheckError error
|
||||
// PendingDownload holds the resources that are pending download.
|
||||
PendingDownload []string
|
||||
|
||||
// LastDownloadAt holds the time when resources were downloaded the last time.
|
||||
LastDownloadAt *time.Time
|
||||
// LastDownloadError holds the error of the last download.
|
||||
LastDownloadError error
|
||||
// LastDownload holds the resources that we downloaded the last time updates
|
||||
// were downloaded.
|
||||
LastDownload []string
|
||||
|
||||
// LastSuccessAt holds the time of the last successful update (check).
|
||||
LastSuccessAt *time.Time
|
||||
}
|
||||
|
||||
// GetState returns the current registry state.
|
||||
// The returned data must not be modified.
|
||||
func (reg *ResourceRegistry) GetState() RegistryState {
|
||||
reg.state.Lock()
|
||||
defer reg.state.Unlock()
|
||||
|
||||
return RegistryState{
|
||||
ID: reg.state.ID,
|
||||
Details: reg.state.Details,
|
||||
Updates: reg.state.Updates,
|
||||
}
|
||||
}
|
||||
|
||||
// StartOperation starts an operation.
|
||||
func (s *RegistryState) StartOperation(id string) bool {
|
||||
defer s.notify()
|
||||
|
||||
s.operationLock.Lock()
|
||||
|
||||
s.Lock()
|
||||
defer s.Unlock()
|
||||
|
||||
s.ID = id
|
||||
return true
|
||||
}
|
||||
|
||||
// UpdateOperationDetails updates the details of an operation.
|
||||
// The supplied struct should be a copy and must not be changed after calling
|
||||
// this function.
|
||||
func (s *RegistryState) UpdateOperationDetails(details any) {
|
||||
defer s.notify()
|
||||
|
||||
s.Lock()
|
||||
defer s.Unlock()
|
||||
|
||||
s.Details = details
|
||||
}
|
||||
|
||||
// EndOperation ends an operation.
|
||||
func (s *RegistryState) EndOperation() {
|
||||
defer s.notify()
|
||||
defer s.operationLock.Unlock()
|
||||
|
||||
s.Lock()
|
||||
defer s.Unlock()
|
||||
|
||||
s.ID = StateReady
|
||||
s.Details = nil
|
||||
}
|
||||
|
||||
// ReportUpdateCheck reports an update check to the registry state.
|
||||
func (s *RegistryState) ReportUpdateCheck(pendingDownload []string, failed error) {
|
||||
defer s.notify()
|
||||
|
||||
sort.Strings(pendingDownload)
|
||||
|
||||
s.Lock()
|
||||
defer s.Unlock()
|
||||
|
||||
now := time.Now()
|
||||
s.Updates.LastCheckAt = &now
|
||||
s.Updates.LastCheckError = failed
|
||||
s.Updates.PendingDownload = pendingDownload
|
||||
|
||||
if failed == nil {
|
||||
s.Updates.LastSuccessAt = &now
|
||||
}
|
||||
}
|
||||
|
||||
// ReportDownloads reports downloaded updates to the registry state.
|
||||
func (s *RegistryState) ReportDownloads(downloaded []string, failed error) {
|
||||
defer s.notify()
|
||||
|
||||
sort.Strings(downloaded)
|
||||
|
||||
s.Lock()
|
||||
defer s.Unlock()
|
||||
|
||||
now := time.Now()
|
||||
s.Updates.LastDownloadAt = &now
|
||||
s.Updates.LastDownloadError = failed
|
||||
s.Updates.LastDownload = downloaded
|
||||
|
||||
// Remove downloaded resources from the pending list.
|
||||
if len(s.Updates.PendingDownload) > 0 {
|
||||
newPendingDownload := make([]string, 0, len(s.Updates.PendingDownload))
|
||||
for _, pending := range s.Updates.PendingDownload {
|
||||
if !utils.StringInSlice(downloaded, pending) {
|
||||
newPendingDownload = append(newPendingDownload, pending)
|
||||
}
|
||||
}
|
||||
s.Updates.PendingDownload = newPendingDownload
|
||||
}
|
||||
|
||||
if failed == nil {
|
||||
s.Updates.LastSuccessAt = &now
|
||||
}
|
||||
}
|
||||
|
||||
func (s *RegistryState) notify() {
|
||||
switch {
|
||||
case s.reg == nil:
|
||||
return
|
||||
case s.reg.StateNotifyFunc == nil:
|
||||
return
|
||||
}
|
||||
|
||||
s.reg.StateNotifyFunc(s)
|
||||
}
|
||||
Reference in New Issue
Block a user