Simplify and improve update version export
This commit is contained in:
@@ -2,11 +2,8 @@ package updates
|
|||||||
|
|
||||||
import (
|
import (
|
||||||
"context"
|
"context"
|
||||||
"errors"
|
|
||||||
"sync"
|
"sync"
|
||||||
|
|
||||||
"github.com/safing/portbase/database"
|
|
||||||
"github.com/safing/portbase/database/query"
|
|
||||||
"github.com/safing/portbase/database/record"
|
"github.com/safing/portbase/database/record"
|
||||||
"github.com/safing/portbase/info"
|
"github.com/safing/portbase/info"
|
||||||
"github.com/safing/portbase/log"
|
"github.com/safing/portbase/log"
|
||||||
@@ -14,48 +11,95 @@ import (
|
|||||||
"github.com/safing/portmaster/updates/helper"
|
"github.com/safing/portmaster/updates/helper"
|
||||||
)
|
)
|
||||||
|
|
||||||
// Database key for update information.
|
|
||||||
const (
|
const (
|
||||||
|
// versionsDBKey is the database key for update version information.
|
||||||
versionsDBKey = "core:status/versions"
|
versionsDBKey = "core:status/versions"
|
||||||
|
|
||||||
|
// versionsDBKey is the database key for simple update version information.
|
||||||
|
simpleVersionsDBKey = "core:status/simple-versions"
|
||||||
)
|
)
|
||||||
|
|
||||||
var (
|
// Versions holds update versions and status information.
|
||||||
versionExport *versions
|
type Versions struct {
|
||||||
versionExportDB = database.NewInterface(&database.Options{
|
|
||||||
Local: true,
|
|
||||||
Internal: true,
|
|
||||||
})
|
|
||||||
versionExportHook *database.RegisteredHook
|
|
||||||
)
|
|
||||||
|
|
||||||
// versions holds updates status information.
|
|
||||||
type versions struct {
|
|
||||||
record.Base
|
record.Base
|
||||||
lock sync.Mutex
|
sync.Mutex
|
||||||
|
|
||||||
Core *info.Info
|
Core *info.Info
|
||||||
Resources map[string]*updater.Resource
|
Resources map[string]*updater.Resource
|
||||||
Channel string
|
Channel string
|
||||||
Beta bool
|
Beta bool
|
||||||
Staging bool
|
Staging bool
|
||||||
|
}
|
||||||
|
|
||||||
internalSave bool
|
// SimpleVersions holds simplified update versions and status information.
|
||||||
|
type SimpleVersions struct {
|
||||||
|
record.Base
|
||||||
|
sync.Mutex
|
||||||
|
|
||||||
|
Build *info.Info
|
||||||
|
Resources map[string]*SimplifiedResourceVersion
|
||||||
|
Channel string
|
||||||
|
}
|
||||||
|
|
||||||
|
// SimplifiedResourceVersion holds version information about one resource.
|
||||||
|
type SimplifiedResourceVersion struct {
|
||||||
|
Version string
|
||||||
|
}
|
||||||
|
|
||||||
|
// GetVersions returns the update versions and status information.
|
||||||
|
// Resources must be locked when accessed.
|
||||||
|
func GetVersions() *Versions {
|
||||||
|
return &Versions{
|
||||||
|
Core: info.GetInfo(),
|
||||||
|
Resources: registry.Export(),
|
||||||
|
Channel: initialReleaseChannel,
|
||||||
|
Beta: initialReleaseChannel == helper.ReleaseChannelBeta,
|
||||||
|
Staging: initialReleaseChannel == helper.ReleaseChannelStaging,
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
// GetSimpleVersions returns the simplified update versions and status information.
|
||||||
|
func GetSimpleVersions() *SimpleVersions {
|
||||||
|
// Fill base info.
|
||||||
|
v := &SimpleVersions{
|
||||||
|
Build: info.GetInfo(),
|
||||||
|
Resources: make(map[string]*SimplifiedResourceVersion),
|
||||||
|
Channel: initialReleaseChannel,
|
||||||
|
}
|
||||||
|
|
||||||
|
// Iterate through all versions and add version info.
|
||||||
|
for id, resource := range registry.Export() {
|
||||||
|
func() {
|
||||||
|
resource.Lock()
|
||||||
|
defer resource.Unlock()
|
||||||
|
|
||||||
|
// Get current in-used or selected version.
|
||||||
|
var rv *updater.ResourceVersion
|
||||||
|
switch {
|
||||||
|
case resource.ActiveVersion != nil:
|
||||||
|
rv = resource.ActiveVersion
|
||||||
|
case resource.SelectedVersion != nil:
|
||||||
|
rv = resource.SelectedVersion
|
||||||
|
}
|
||||||
|
|
||||||
|
// Get information from resource.
|
||||||
|
if rv != nil {
|
||||||
|
v.Resources[id] = &SimplifiedResourceVersion{
|
||||||
|
Version: rv.VersionNumber,
|
||||||
|
}
|
||||||
|
}
|
||||||
|
}()
|
||||||
|
}
|
||||||
|
|
||||||
|
return v
|
||||||
}
|
}
|
||||||
|
|
||||||
func initVersionExport() (err error) {
|
func initVersionExport() (err error) {
|
||||||
// init export struct
|
if err := GetVersions().save(); err != nil {
|
||||||
versionExport = &versions{
|
log.Warningf("updates: failed to export version information: %s", err)
|
||||||
internalSave: true,
|
|
||||||
Channel: initialReleaseChannel,
|
|
||||||
Beta: initialReleaseChannel == helper.ReleaseChannelBeta,
|
|
||||||
Staging: initialReleaseChannel == helper.ReleaseChannelStaging,
|
|
||||||
}
|
}
|
||||||
versionExport.SetKey(versionsDBKey)
|
if err := GetSimpleVersions().save(); err != nil {
|
||||||
|
log.Warningf("updates: failed to export version information: %s", err)
|
||||||
// attach hook to database
|
|
||||||
versionExportHook, err = database.RegisterHook(query.New(versionsDBKey), &exportHook{})
|
|
||||||
if err != nil {
|
|
||||||
return err
|
|
||||||
}
|
}
|
||||||
|
|
||||||
return module.RegisterEventHook(
|
return module.RegisterEventHook(
|
||||||
@@ -66,71 +110,24 @@ func initVersionExport() (err error) {
|
|||||||
)
|
)
|
||||||
}
|
}
|
||||||
|
|
||||||
func stopVersionExport() error {
|
func (v *Versions) save() error {
|
||||||
return versionExportHook.Cancel()
|
if !v.KeyIsSet() {
|
||||||
|
v.SetKey(versionsDBKey)
|
||||||
|
}
|
||||||
|
return db.Put(v)
|
||||||
|
}
|
||||||
|
|
||||||
|
func (v *SimpleVersions) save() error {
|
||||||
|
if !v.KeyIsSet() {
|
||||||
|
v.SetKey(simpleVersionsDBKey)
|
||||||
|
}
|
||||||
|
return db.Put(v)
|
||||||
}
|
}
|
||||||
|
|
||||||
// export is an event hook.
|
// export is an event hook.
|
||||||
func export(_ context.Context, _ interface{}) error {
|
func export(_ context.Context, _ interface{}) error {
|
||||||
// populate
|
if err := GetVersions().save(); err != nil {
|
||||||
versionExport.lock.Lock()
|
return err
|
||||||
versionExport.Core = info.GetInfo()
|
|
||||||
versionExport.Resources = registry.Export()
|
|
||||||
versionExport.lock.Unlock()
|
|
||||||
|
|
||||||
// save
|
|
||||||
err := versionExportDB.Put(versionExport)
|
|
||||||
if err != nil {
|
|
||||||
log.Warningf("updates: failed to export versions: %s", err)
|
|
||||||
}
|
}
|
||||||
|
return GetSimpleVersions().save()
|
||||||
return nil
|
|
||||||
}
|
|
||||||
|
|
||||||
// Lock locks the versionExport and all associated resources.
|
|
||||||
func (v *versions) Lock() {
|
|
||||||
// lock self
|
|
||||||
v.lock.Lock()
|
|
||||||
|
|
||||||
// lock all resources
|
|
||||||
for _, res := range v.Resources {
|
|
||||||
res.Lock()
|
|
||||||
}
|
|
||||||
}
|
|
||||||
|
|
||||||
// Lock unlocks the versionExport and all associated resources.
|
|
||||||
func (v *versions) Unlock() {
|
|
||||||
// unlock all resources
|
|
||||||
for _, res := range v.Resources {
|
|
||||||
res.Unlock()
|
|
||||||
}
|
|
||||||
|
|
||||||
// unlock self
|
|
||||||
v.lock.Unlock()
|
|
||||||
}
|
|
||||||
|
|
||||||
type exportHook struct {
|
|
||||||
database.HookBase
|
|
||||||
}
|
|
||||||
|
|
||||||
// UsesPrePut implements the Hook interface.
|
|
||||||
func (eh *exportHook) UsesPrePut() bool {
|
|
||||||
return true
|
|
||||||
}
|
|
||||||
|
|
||||||
var errInternalRecord = errors.New("may not modify internal record")
|
|
||||||
|
|
||||||
// PrePut implements the Hook interface.
|
|
||||||
func (eh *exportHook) PrePut(r record.Record) (record.Record, error) {
|
|
||||||
if r.IsWrapped() {
|
|
||||||
return nil, errInternalRecord
|
|
||||||
}
|
|
||||||
ve, ok := r.(*versions)
|
|
||||||
if !ok {
|
|
||||||
return nil, errInternalRecord
|
|
||||||
}
|
|
||||||
if !ve.internalSave {
|
|
||||||
return nil, errInternalRecord
|
|
||||||
}
|
|
||||||
return r, nil
|
|
||||||
}
|
}
|
||||||
|
|||||||
@@ -7,6 +7,7 @@ import (
|
|||||||
"runtime"
|
"runtime"
|
||||||
"time"
|
"time"
|
||||||
|
|
||||||
|
"github.com/safing/portbase/database"
|
||||||
"github.com/safing/portbase/dataroot"
|
"github.com/safing/portbase/dataroot"
|
||||||
"github.com/safing/portbase/log"
|
"github.com/safing/portbase/log"
|
||||||
"github.com/safing/portbase/modules"
|
"github.com/safing/portbase/modules"
|
||||||
@@ -48,6 +49,11 @@ var (
|
|||||||
updateASAP bool
|
updateASAP bool
|
||||||
disableTaskSchedule bool
|
disableTaskSchedule bool
|
||||||
|
|
||||||
|
db = database.NewInterface(&database.Options{
|
||||||
|
Local: true,
|
||||||
|
Internal: true,
|
||||||
|
})
|
||||||
|
|
||||||
// UserAgent is an HTTP User-Agent that is used to add
|
// UserAgent is an HTTP User-Agent that is used to add
|
||||||
// more context to requests made by the registry when
|
// more context to requests made by the registry when
|
||||||
// fetching resources from the update server.
|
// fetching resources from the update server.
|
||||||
@@ -55,6 +61,8 @@ var (
|
|||||||
)
|
)
|
||||||
|
|
||||||
const (
|
const (
|
||||||
|
updatesDirName = "updates"
|
||||||
|
|
||||||
updateFailed = "updates:failed"
|
updateFailed = "updates:failed"
|
||||||
updateSuccess = "updates:success"
|
updateSuccess = "updates:success"
|
||||||
)
|
)
|
||||||
@@ -108,7 +116,7 @@ func start() error {
|
|||||||
registry.UserAgent = userAgentFromFlag
|
registry.UserAgent = userAgentFromFlag
|
||||||
}
|
}
|
||||||
// initialize
|
// initialize
|
||||||
err := registry.Initialize(dataroot.Root().ChildDir("updates", 0o0755))
|
err := registry.Initialize(dataroot.Root().ChildDir(updatesDirName, 0o0755))
|
||||||
if err != nil {
|
if err != nil {
|
||||||
return err
|
return err
|
||||||
}
|
}
|
||||||
@@ -275,7 +283,7 @@ func stop() error {
|
|||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
return stopVersionExport()
|
return nil
|
||||||
}
|
}
|
||||||
|
|
||||||
// RootPath returns the root path used for storing updates.
|
// RootPath returns the root path used for storing updates.
|
||||||
|
|||||||
Reference in New Issue
Block a user