1 package cache
2
3 import (
4 "context"
5 "time"
6
7 "github.com/LINBIT/golinstor/client"
8 )
9
10
11 type ResourceCache struct {
12
13 Timeout time.Duration
14
15 resourceCache cache
16 snapshotCache cache
17 }
18
19 func (r *ResourceCache) apply(c *client.Client) {
20 c.Resources = &resourceCacheProvider{
21 cl: c.Resources,
22 cache: r,
23 }
24 }
25
26 type resourceCacheProvider struct {
27 cl client.ResourceProvider
28 cache *ResourceCache
29 }
30
31 var _ client.ResourceProvider = &resourceCacheProvider{}
32
33 func (r *resourceCacheProvider) GetResourceView(ctx context.Context, opts ...*client.ListOpts) ([]client.ResourceWithVolumes, error) {
34 result, err := r.cache.resourceCache.Get(r.cache.Timeout, func() (any, error) {
35 return r.cl.GetResourceView(ctx, cacheOpt)
36 })
37 if err != nil {
38 return nil, err
39 }
40
41 return filterNodeAndPoolOpts(result.([]client.ResourceWithVolumes), func(c *client.ResourceWithVolumes) ([]string, []string) {
42 return []string{c.NodeName}, nil
43 }, opts...), nil
44 }
45
46 func (r *resourceCacheProvider) GetAll(ctx context.Context, resName string, opts ...*client.ListOpts) ([]client.Resource, error) {
47 ress, err := r.GetResourceView(ctx, opts...)
48 if err != nil {
49 return nil, err
50 }
51
52 var result []client.Resource
53
54 for i := range ress {
55 if ress[i].Name == resName {
56 result = append(result, ress[i].Resource)
57 }
58 }
59
60 return result, nil
61 }
62
63 func (r *resourceCacheProvider) Get(ctx context.Context, resName, nodeName string, opts ...*client.ListOpts) (client.Resource, error) {
64 ress, err := r.GetAll(ctx, resName, opts...)
65 if err != nil {
66 return client.Resource{}, err
67 }
68
69 for i := range ress {
70 if ress[i].NodeName == nodeName {
71 return ress[i], nil
72 }
73 }
74 return client.Resource{}, client.NotFoundError
75 }
76
77 func (r *resourceCacheProvider) GetVolumes(ctx context.Context, resName, nodeName string, opts ...*client.ListOpts) ([]client.Volume, error) {
78 ress, err := r.GetResourceView(ctx, opts...)
79 if err != nil {
80 return nil, err
81 }
82
83 var result []client.Volume
84 for i := range ress {
85 if ress[i].NodeName != nodeName || ress[i].Name != resName {
86 continue
87 }
88
89 for j := range ress[i].Volumes {
90 result = append(result, ress[i].Volumes[j])
91 }
92 }
93
94 return result, nil
95 }
96
97 func (r *resourceCacheProvider) GetVolume(ctx context.Context, resName, nodeName string, volNr int, opts ...*client.ListOpts) (client.Volume, error) {
98 volumes, err := r.GetVolumes(ctx, resName, nodeName, opts...)
99 if err != nil {
100 return client.Volume{}, err
101 }
102
103 for i := range volumes {
104 if int(volumes[i].VolumeNumber) == volNr {
105 return volumes[i], nil
106 }
107 }
108
109 return client.Volume{}, client.NotFoundError
110 }
111
112 func (r *resourceCacheProvider) Create(ctx context.Context, res client.ResourceCreate) error {
113 r.cache.resourceCache.Invalidate()
114 return r.cl.Create(ctx, res)
115 }
116
117 func (r *resourceCacheProvider) Modify(ctx context.Context, resName, nodeName string, props client.GenericPropsModify) error {
118 r.cache.resourceCache.Invalidate()
119 return r.cl.Modify(ctx, resName, nodeName, props)
120 }
121
122 func (r *resourceCacheProvider) Delete(ctx context.Context, resName, nodeName string) error {
123 r.cache.resourceCache.Invalidate()
124 return r.cl.Delete(ctx, resName, nodeName)
125 }
126
127 func (r *resourceCacheProvider) ModifyVolume(ctx context.Context, resName, nodeName string, volNr int, props client.GenericPropsModify) error {
128 r.cache.resourceCache.Invalidate()
129 return r.cl.ModifyVolume(ctx, resName, nodeName, volNr, props)
130 }
131
132 func (r *resourceCacheProvider) Diskless(ctx context.Context, resName, nodeName, disklessPoolName string) error {
133 r.cache.resourceCache.Invalidate()
134 return r.cl.Diskless(ctx, resName, nodeName, disklessPoolName)
135 }
136
137 func (r *resourceCacheProvider) Diskful(ctx context.Context, resName, nodeName, storagePoolName string, props *client.ToggleDiskDiskfulProps) error {
138 r.cache.resourceCache.Invalidate()
139 return r.cl.Diskful(ctx, resName, nodeName, storagePoolName, props)
140 }
141
142 func (r *resourceCacheProvider) Migrate(ctx context.Context, resName, fromNodeName, toNodeName, storagePoolName string) error {
143 r.cache.resourceCache.Invalidate()
144 return r.cl.Migrate(ctx, resName, fromNodeName, toNodeName, storagePoolName)
145 }
146
147 func (r *resourceCacheProvider) Autoplace(ctx context.Context, resName string, apr client.AutoPlaceRequest) error {
148 r.cache.resourceCache.Invalidate()
149 return r.cl.Autoplace(ctx, resName, apr)
150 }
151
152 func (r *resourceCacheProvider) Activate(ctx context.Context, resName string, nodeName string) error {
153 r.cache.resourceCache.Invalidate()
154 return r.cl.Activate(ctx, resName, nodeName)
155 }
156
157 func (r *resourceCacheProvider) Deactivate(ctx context.Context, resName string, nodeName string) error {
158 r.cache.resourceCache.Invalidate()
159 return r.cl.Deactivate(ctx, resName, nodeName)
160 }
161
162 func (r *resourceCacheProvider) MakeAvailable(ctx context.Context, resName, nodeName string, makeAvailable client.ResourceMakeAvailable) error {
163 r.cache.resourceCache.Invalidate()
164 return r.cl.MakeAvailable(ctx, resName, nodeName, makeAvailable)
165 }
166
167 func (r *resourceCacheProvider) GetSnapshotView(ctx context.Context, opts ...*client.ListOpts) ([]client.Snapshot, error) {
168 result, err := r.cache.snapshotCache.Get(r.cache.Timeout, func() (any, error) {
169 return r.cl.GetSnapshotView(ctx, cacheOpt)
170 })
171 if err != nil {
172 return nil, err
173 }
174
175 return filterNodeAndPoolOpts(result.([]client.Snapshot), func(c *client.Snapshot) ([]string, []string) {
176 return c.Nodes, nil
177 }, opts...), nil
178 }
179
180 func (r *resourceCacheProvider) GetSnapshots(ctx context.Context, resName string, opts ...*client.ListOpts) ([]client.Snapshot, error) {
181 snaps, err := r.GetSnapshotView(ctx, opts...)
182 if err != nil {
183 return nil, err
184 }
185
186 var result []client.Snapshot
187 for i := range snaps {
188 if snaps[i].ResourceName == resName {
189 result = append(result, snaps[i])
190 }
191 }
192
193 return result, nil
194 }
195
196 func (r *resourceCacheProvider) GetSnapshot(ctx context.Context, resName, snapName string, opts ...*client.ListOpts) (client.Snapshot, error) {
197 snaps, err := r.GetSnapshots(ctx, resName, opts...)
198 if err != nil {
199 return client.Snapshot{}, err
200 }
201
202 for i := range snaps {
203 if snaps[i].Name == snapName {
204 return snaps[i], nil
205 }
206 }
207
208 return client.Snapshot{}, client.NotFoundError
209 }
210
211 func (r *resourceCacheProvider) CreateSnapshot(ctx context.Context, snapshot client.Snapshot) error {
212 r.cache.snapshotCache.Invalidate()
213 return r.cl.CreateSnapshot(ctx, snapshot)
214 }
215
216 func (r *resourceCacheProvider) DeleteSnapshot(ctx context.Context, resName, snapName string, nodes ...string) error {
217 r.cache.snapshotCache.Invalidate()
218 return r.cl.DeleteSnapshot(ctx, resName, snapName, nodes...)
219 }
220
221 func (r *resourceCacheProvider) RestoreSnapshot(ctx context.Context, origResName, snapName string, snapRestoreConf client.SnapshotRestore) error {
222
223 r.cache.resourceCache.Invalidate()
224 return r.cl.RestoreSnapshot(ctx, origResName, snapName, snapRestoreConf)
225 }
226
227 func (r *resourceCacheProvider) RestoreVolumeDefinitionSnapshot(ctx context.Context, origResName, snapName string, snapRestoreConf client.SnapshotRestore) error {
228
229 r.cache.resourceCache.Invalidate()
230 return r.cl.RestoreVolumeDefinitionSnapshot(ctx, origResName, snapName, snapRestoreConf)
231 }
232
233 func (r *resourceCacheProvider) RollbackSnapshot(ctx context.Context, resName, snapName string) error {
234 return r.cl.RollbackSnapshot(ctx, resName, snapName)
235 }
236
237 func (r *resourceCacheProvider) GetConnections(ctx context.Context, resName, nodeAName, nodeBName string, opts ...*client.ListOpts) ([]client.ResourceConnection, error) {
238 return r.cl.GetConnections(ctx, resName, nodeAName, nodeBName, opts...)
239 }
240
241 func (r *resourceCacheProvider) ModifyConnection(ctx context.Context, resName, nodeAName, nodeBName string, props client.GenericPropsModify) error {
242 return r.cl.ModifyConnection(ctx, resName, nodeAName, nodeBName, props)
243 }
244
245 func (r *resourceCacheProvider) EnableSnapshotShipping(ctx context.Context, resName string, ship client.SnapshotShipping) error {
246 return r.cl.EnableSnapshotShipping(ctx, resName, ship)
247 }
248
249 func (r *resourceCacheProvider) ModifyDRBDProxy(ctx context.Context, resName string, props client.DrbdProxyModify) error {
250 return r.cl.ModifyDRBDProxy(ctx, resName, props)
251 }
252
253 func (r *resourceCacheProvider) EnableDRBDProxy(ctx context.Context, resName, nodeAName, nodeBName string) error {
254 return r.cl.EnableDRBDProxy(ctx, resName, nodeAName, nodeBName)
255 }
256
257 func (r *resourceCacheProvider) DisableDRBDProxy(ctx context.Context, resName, nodeAName, nodeBName string) error {
258 return r.cl.DisableDRBDProxy(ctx, resName, nodeAName, nodeBName)
259 }
260
261 func (r *resourceCacheProvider) QueryMaxVolumeSize(ctx context.Context, filter client.AutoSelectFilter) (client.MaxVolumeSizes, error) {
262 return r.cl.QueryMaxVolumeSize(ctx, filter)
263 }
264
265 func (r *resourceCacheProvider) GetSnapshotShippings(ctx context.Context, opts ...*client.ListOpts) ([]client.SnapshotShippingStatus, error) {
266 return r.cl.GetSnapshotShippings(ctx, opts...)
267 }
268
269 func (r *resourceCacheProvider) GetPropsInfos(ctx context.Context, resName string, opts ...*client.ListOpts) ([]client.PropsInfo, error) {
270 return r.cl.GetPropsInfos(ctx, resName, opts...)
271 }
272
273 func (r *resourceCacheProvider) GetVolumeDefinitionPropsInfos(ctx context.Context, resName string, opts ...*client.ListOpts) ([]client.PropsInfo, error) {
274 return r.cl.GetVolumeDefinitionPropsInfos(ctx, resName, opts...)
275 }
276
277 func (r *resourceCacheProvider) GetVolumePropsInfos(ctx context.Context, resName, nodeName string, opts ...*client.ListOpts) ([]client.PropsInfo, error) {
278 return r.cl.GetVolumePropsInfos(ctx, resName, nodeName, opts...)
279 }
280
281 func (r *resourceCacheProvider) GetConnectionPropsInfos(ctx context.Context, resName string, opts ...*client.ListOpts) ([]client.PropsInfo, error) {
282 return r.cl.GetConnectionPropsInfos(ctx, resName, opts...)
283 }
284
View as plain text