-
-
Notifications
You must be signed in to change notification settings - Fork 274
/
export.go
136 lines (114 loc) Β· 2.77 KB
/
export.go
1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
20
21
22
23
24
25
26
27
28
29
30
31
32
33
34
35
36
37
38
39
40
41
42
43
44
45
46
47
48
49
50
51
52
53
54
55
56
57
58
59
60
61
62
63
64
65
66
67
68
69
70
71
72
73
74
75
76
77
78
79
80
81
82
83
84
85
86
87
88
89
90
91
92
93
94
95
96
97
98
99
100
101
102
103
104
105
106
107
108
109
110
111
112
113
114
115
116
117
118
119
120
121
122
123
124
125
126
127
128
129
130
131
132
133
134
135
136
package updates
import (
"context"
"errors"
"sync"
"github.com/safing/portbase/database"
"github.com/safing/portbase/database/query"
"github.com/safing/portbase/database/record"
"github.com/safing/portbase/info"
"github.com/safing/portbase/log"
"github.com/safing/portbase/updater"
"github.com/safing/portmaster/updates/helper"
)
// Database key for update information.
const (
versionsDBKey = "core:status/versions"
)
var (
versionExport *versions
versionExportDB = database.NewInterface(&database.Options{
Local: true,
Internal: true,
})
versionExportHook *database.RegisteredHook
)
// versions holds updates status information.
type versions struct {
record.Base
lock sync.Mutex
Core *info.Info
Resources map[string]*updater.Resource
Channel string
Beta bool
Staging bool
internalSave bool
}
func initVersionExport() (err error) {
// init export struct
versionExport = &versions{
internalSave: true,
Channel: initialReleaseChannel,
Beta: initialReleaseChannel == helper.ReleaseChannelBeta,
Staging: initialReleaseChannel == helper.ReleaseChannelStaging,
}
versionExport.SetKey(versionsDBKey)
// attach hook to database
versionExportHook, err = database.RegisterHook(query.New(versionsDBKey), &exportHook{})
if err != nil {
return err
}
return module.RegisterEventHook(
ModuleName,
VersionUpdateEvent,
"export version status",
export,
)
}
func stopVersionExport() error {
return versionExportHook.Cancel()
}
// export is an event hook.
func export(_ context.Context, _ interface{}) error {
// populate
versionExport.lock.Lock()
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 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
}