blob: 6900c5ddb988ad43e623714b511e32c44db3e933 [file] [log] [blame]
Stephane Barbarieec0919b2018-09-05 14:14:29 -04001/*
2 * Copyright 2018-present Open Networking Foundation
3
4 * Licensed under the Apache License, Version 2.0 (the "License");
5 * you may not use this file except in compliance with the License.
6 * You may obtain a copy of the License at
7
8 * http://www.apache.org/licenses/LICENSE-2.0
9
10 * Unless required by applicable law or agreed to in writing, software
11 * distributed under the License is distributed on an "AS IS" BASIS,
12 * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
13 * See the License for the specific language governing permissions and
14 * limitations under the License.
15 */
16package model
17
18import (
19 "bytes"
Stephane Barbarieef6650d2019-07-18 12:15:09 -040020 "context"
Stephane Barbarieec0919b2018-09-05 14:14:29 -040021 "crypto/md5"
22 "fmt"
Stephane Barbarie126101e2018-10-11 16:18:48 -040023 "github.com/golang/protobuf/proto"
Stephane Barbarie933b09b2019-01-09 11:12:09 -050024 "github.com/opencord/voltha-go/common/log"
Stephane Barbarie7512fc82019-05-07 12:25:46 -040025 "github.com/opencord/voltha-go/db/kvstore"
Stephane Barbarieec0919b2018-09-05 14:14:29 -040026 "reflect"
27 "sort"
Stephane Barbariedc5022d2018-11-19 15:21:44 -050028 "sync"
Stephane Barbarie802aca42019-05-21 12:19:28 -040029 "time"
Stephane Barbarieec0919b2018-09-05 14:14:29 -040030)
31
Stephane Barbarie40fd3b22019-04-23 21:50:47 -040032// TODO: Cache logic will have to be revisited to cleanup unused entries in memory (disabled for now)
33//
Stephane Barbarie7512fc82019-05-07 12:25:46 -040034type revCacheSingleton struct {
35 sync.RWMutex
36 Cache sync.Map
37}
38
Stephane Barbarieef6650d2019-07-18 12:15:09 -040039func (s *revCacheSingleton) Get(path string) (interface{}, bool) {
40 return s.Cache.Load(path)
41}
42func (s *revCacheSingleton) Set(path string, value interface{}) {
43 s.Cache.Store(path, value)
44}
45func (s *revCacheSingleton) Delete(path string) {
46 s.Cache.Delete(path)
47}
48
Stephane Barbarie7512fc82019-05-07 12:25:46 -040049var revCacheInstance *revCacheSingleton
50var revCacheOnce sync.Once
51
52func GetRevCache() *revCacheSingleton {
53 revCacheOnce.Do(func() {
54 revCacheInstance = &revCacheSingleton{Cache: sync.Map{}}
55 })
56 return revCacheInstance
57}
Stephane Barbarieec0919b2018-09-05 14:14:29 -040058
59type NonPersistedRevision struct {
Stephane Barbarie40fd3b22019-04-23 21:50:47 -040060 mutex sync.RWMutex
61 Root *root
62 Config *DataRevision
63 childrenLock sync.RWMutex
64 Children map[string][]Revision
65 Hash string
66 Branch *Branch
67 WeakRef string
68 Name string
Stephane Barbarie802aca42019-05-21 12:19:28 -040069 lastUpdate time.Time
Stephane Barbarieec0919b2018-09-05 14:14:29 -040070}
71
Stephane Barbariedc5022d2018-11-19 15:21:44 -050072func NewNonPersistedRevision(root *root, branch *Branch, data interface{}, children map[string][]Revision) Revision {
73 r := &NonPersistedRevision{}
74 r.Root = root
75 r.Branch = branch
76 r.Config = NewDataRevision(root, data)
77 r.Children = children
Stephane Barbarief7fc1782019-03-28 22:33:41 -040078 r.Hash = r.hashContent()
Stephane Barbariedc5022d2018-11-19 15:21:44 -050079 return r
Stephane Barbarieec0919b2018-09-05 14:14:29 -040080}
81
82func (npr *NonPersistedRevision) SetConfig(config *DataRevision) {
Stephane Barbariedc5022d2018-11-19 15:21:44 -050083 npr.mutex.Lock()
84 defer npr.mutex.Unlock()
Stephane Barbarieec0919b2018-09-05 14:14:29 -040085 npr.Config = config
86}
87
88func (npr *NonPersistedRevision) GetConfig() *DataRevision {
Stephane Barbariedc5022d2018-11-19 15:21:44 -050089 npr.mutex.Lock()
90 defer npr.mutex.Unlock()
Stephane Barbarieec0919b2018-09-05 14:14:29 -040091 return npr.Config
92}
93
Stephane Barbarie3cb01222019-01-16 17:15:56 -050094func (npr *NonPersistedRevision) SetAllChildren(children map[string][]Revision) {
Stephane Barbarie40fd3b22019-04-23 21:50:47 -040095 npr.childrenLock.Lock()
96 defer npr.childrenLock.Unlock()
97 npr.Children = make(map[string][]Revision)
Stephane Barbarieec0919b2018-09-05 14:14:29 -040098
Stephane Barbarie40fd3b22019-04-23 21:50:47 -040099 for key, value := range children {
100 npr.Children[key] = make([]Revision, len(value))
101 copy(npr.Children[key], value)
Stephane Barbarie3cb01222019-01-16 17:15:56 -0500102 }
103}
104
Stephane Barbarie40fd3b22019-04-23 21:50:47 -0400105func (npr *NonPersistedRevision) SetChildren(name string, children []Revision) {
106 npr.childrenLock.Lock()
107 defer npr.childrenLock.Unlock()
108
109 npr.Children[name] = make([]Revision, len(children))
110 copy(npr.Children[name], children)
111}
112
Stephane Barbarie3cb01222019-01-16 17:15:56 -0500113func (npr *NonPersistedRevision) GetAllChildren() map[string][]Revision {
Stephane Barbarie40fd3b22019-04-23 21:50:47 -0400114 npr.childrenLock.Lock()
115 defer npr.childrenLock.Unlock()
116
Stephane Barbarieec0919b2018-09-05 14:14:29 -0400117 return npr.Children
118}
119
Stephane Barbarie3cb01222019-01-16 17:15:56 -0500120func (npr *NonPersistedRevision) GetChildren(name string) []Revision {
Stephane Barbarie40fd3b22019-04-23 21:50:47 -0400121 npr.childrenLock.Lock()
122 defer npr.childrenLock.Unlock()
123
Stephane Barbarie3cb01222019-01-16 17:15:56 -0500124 if _, exists := npr.Children[name]; exists {
125 return npr.Children[name]
126 }
127 return nil
128}
129
Stephane Barbarieec0919b2018-09-05 14:14:29 -0400130func (npr *NonPersistedRevision) SetHash(hash string) {
Stephane Barbariedc5022d2018-11-19 15:21:44 -0500131 npr.mutex.Lock()
132 defer npr.mutex.Unlock()
Stephane Barbarieec0919b2018-09-05 14:14:29 -0400133 npr.Hash = hash
134}
135
136func (npr *NonPersistedRevision) GetHash() string {
Stephane Barbariedc5022d2018-11-19 15:21:44 -0500137 //npr.mutex.Lock()
138 //defer npr.mutex.Unlock()
Stephane Barbarieec0919b2018-09-05 14:14:29 -0400139 return npr.Hash
140}
141
142func (npr *NonPersistedRevision) ClearHash() {
Stephane Barbariedc5022d2018-11-19 15:21:44 -0500143 npr.mutex.Lock()
144 defer npr.mutex.Unlock()
Stephane Barbarieec0919b2018-09-05 14:14:29 -0400145 npr.Hash = ""
146}
147
Stephane Barbarief7fc1782019-03-28 22:33:41 -0400148func (npr *NonPersistedRevision) GetName() string {
149 //npr.mutex.Lock()
150 //defer npr.mutex.Unlock()
151 return npr.Name
152}
153
154func (npr *NonPersistedRevision) SetName(name string) {
155 //npr.mutex.Lock()
156 //defer npr.mutex.Unlock()
157 npr.Name = name
158}
Stephane Barbarieec0919b2018-09-05 14:14:29 -0400159func (npr *NonPersistedRevision) SetBranch(branch *Branch) {
Stephane Barbariedc5022d2018-11-19 15:21:44 -0500160 npr.mutex.Lock()
161 defer npr.mutex.Unlock()
Stephane Barbarieec0919b2018-09-05 14:14:29 -0400162 npr.Branch = branch
163}
164
165func (npr *NonPersistedRevision) GetBranch() *Branch {
Stephane Barbariedc5022d2018-11-19 15:21:44 -0500166 npr.mutex.Lock()
167 defer npr.mutex.Unlock()
Stephane Barbarieec0919b2018-09-05 14:14:29 -0400168 return npr.Branch
169}
170
171func (npr *NonPersistedRevision) GetData() interface{} {
Stephane Barbariedc5022d2018-11-19 15:21:44 -0500172 npr.mutex.Lock()
173 defer npr.mutex.Unlock()
Stephane Barbarieec0919b2018-09-05 14:14:29 -0400174 if npr.Config == nil {
175 return nil
176 }
177 return npr.Config.Data
178}
179
Stephane Barbarie06c4a742018-10-01 11:09:32 -0400180func (npr *NonPersistedRevision) GetNode() *node {
Stephane Barbariedc5022d2018-11-19 15:21:44 -0500181 npr.mutex.Lock()
182 defer npr.mutex.Unlock()
Stephane Barbarieec0919b2018-09-05 14:14:29 -0400183 return npr.Branch.Node
184}
185
Stephane Barbarie1ab43272018-12-08 21:42:13 -0500186func (npr *NonPersistedRevision) Finalize(skipOnExist bool) {
Stephane Barbarie40fd3b22019-04-23 21:50:47 -0400187 npr.Hash = npr.hashContent()
Stephane Barbarieec0919b2018-09-05 14:14:29 -0400188}
189
Stephane Barbarie40fd3b22019-04-23 21:50:47 -0400190// hashContent generates a hash string based on the contents of the revision.
191// The string should be unique to avoid conflicts with other revisions
Stephane Barbarieec0919b2018-09-05 14:14:29 -0400192func (npr *NonPersistedRevision) hashContent() string {
193 var buffer bytes.Buffer
194 var childrenKeys []string
195
196 if npr.Config != nil {
197 buffer.WriteString(npr.Config.Hash)
198 }
199
Stephane Barbarie40fd3b22019-04-23 21:50:47 -0400200 if npr.Name != "" {
201 buffer.WriteString(npr.Name)
202 }
203
Stephane Barbariedc5022d2018-11-19 15:21:44 -0500204 for key := range npr.Children {
Stephane Barbarieec0919b2018-09-05 14:14:29 -0400205 childrenKeys = append(childrenKeys, key)
206 }
Stephane Barbariedc5022d2018-11-19 15:21:44 -0500207
Stephane Barbarieec0919b2018-09-05 14:14:29 -0400208 sort.Strings(childrenKeys)
209
Stephane Barbariedc5022d2018-11-19 15:21:44 -0500210 if len(npr.Children) > 0 {
Stephane Barbarieec0919b2018-09-05 14:14:29 -0400211 // Loop through sorted Children keys
212 for _, key := range childrenKeys {
213 for _, child := range npr.Children[key] {
214 if child != nil && child.GetHash() != "" {
215 buffer.WriteString(child.GetHash())
216 }
217 }
218 }
219 }
220
221 return fmt.Sprintf("%x", md5.Sum(buffer.Bytes()))[:12]
222}
223
Stephane Barbarie40fd3b22019-04-23 21:50:47 -0400224// Get will retrieve the data for the current revision
Stephane Barbarieec0919b2018-09-05 14:14:29 -0400225func (npr *NonPersistedRevision) Get(depth int) interface{} {
Stephane Barbariedc5022d2018-11-19 15:21:44 -0500226 // 1. Clone the data to avoid any concurrent access issues
227 // 2. The current rev might still be pointing to an old config
228 // thus, force the revision to get its latest value
229 latestRev := npr.GetBranch().GetLatest()
230 originalData := proto.Clone(latestRev.GetData().(proto.Message))
Stephane Barbariedc5022d2018-11-19 15:21:44 -0500231 data := originalData
Stephane Barbarieec0919b2018-09-05 14:14:29 -0400232
233 if depth != 0 {
Stephane Barbarie40fd3b22019-04-23 21:50:47 -0400234 // FIXME: Traversing the struct through reflection sometimes corrupts the data.
235 // Unlike the original python implementation, golang structs are not lazy loaded.
236 // Keeping this non-critical logic for now, but Get operations should be forced to
237 // depth=0 to avoid going through the following loop.
Stephane Barbariedc5022d2018-11-19 15:21:44 -0500238 for fieldName, field := range ChildrenFields(latestRev.GetData()) {
Stephane Barbarieec0919b2018-09-05 14:14:29 -0400239 childDataName, childDataHolder := GetAttributeValue(data, fieldName, 0)
240 if field.IsContainer {
Stephane Barbarie3cb01222019-01-16 17:15:56 -0500241 for _, rev := range latestRev.GetChildren(fieldName) {
Stephane Barbarieec0919b2018-09-05 14:14:29 -0400242 childData := rev.Get(depth - 1)
Stephane Barbarie88fbe7f2018-09-25 12:25:23 -0400243 foundEntry := false
244 for i := 0; i < childDataHolder.Len(); i++ {
Stephane Barbariedc5022d2018-11-19 15:21:44 -0500245 cdh_if := childDataHolder.Index(i).Interface()
246 if cdh_if.(proto.Message).String() == childData.(proto.Message).String() {
Stephane Barbarie88fbe7f2018-09-25 12:25:23 -0400247 foundEntry = true
248 break
249 }
250 }
251 if !foundEntry {
Stephane Barbariedc5022d2018-11-19 15:21:44 -0500252 // avoid duplicates by adding it only if the child was not found in the holder
Stephane Barbarie88fbe7f2018-09-25 12:25:23 -0400253 childDataHolder = reflect.Append(childDataHolder, reflect.ValueOf(childData))
254 }
Stephane Barbarieec0919b2018-09-05 14:14:29 -0400255 }
256 } else {
Stephane Barbarie40fd3b22019-04-23 21:50:47 -0400257 if revs := npr.GetBranch().GetLatest().GetChildren(fieldName); revs != nil && len(revs) > 0 {
258 rev := revs[0]
Stephane Barbarie126101e2018-10-11 16:18:48 -0400259 if rev != nil {
260 childData := rev.Get(depth - 1)
261 if reflect.TypeOf(childData) == reflect.TypeOf(childDataHolder.Interface()) {
262 childDataHolder = reflect.ValueOf(childData)
263 }
Stephane Barbarie88fbe7f2018-09-25 12:25:23 -0400264 }
265 }
Stephane Barbarieec0919b2018-09-05 14:14:29 -0400266 }
267 // Merge child data with cloned object
268 reflect.ValueOf(data).Elem().FieldByName(childDataName).Set(childDataHolder)
269 }
270 }
Stephane Barbarie126101e2018-10-11 16:18:48 -0400271
272 result := data
273
274 if result != nil {
Stephane Barbariedc5022d2018-11-19 15:21:44 -0500275 // We need to send back a copy of the retrieved object
276 result = proto.Clone(data.(proto.Message))
Stephane Barbarie126101e2018-10-11 16:18:48 -0400277 }
278
279 return result
Stephane Barbarieec0919b2018-09-05 14:14:29 -0400280}
281
Stephane Barbarie40fd3b22019-04-23 21:50:47 -0400282// UpdateData will refresh the data content of the revision
Stephane Barbarieef6650d2019-07-18 12:15:09 -0400283func (npr *NonPersistedRevision) UpdateData(ctx context.Context, data interface{}, branch *Branch) Revision {
Stephane Barbariedc5022d2018-11-19 15:21:44 -0500284 npr.mutex.Lock()
285 defer npr.mutex.Unlock()
Stephane Barbarie88fbe7f2018-09-25 12:25:23 -0400286
Stephane Barbarieef6650d2019-07-18 12:15:09 -0400287 if ctx != nil {
288 if ctxTS, ok := ctx.Value(RequestTimestamp).(int64); ok && npr.lastUpdate.UnixNano() > ctxTS {
289 log.Warnw("data-is-older-than-current", log.Fields{"ctx-ts": ctxTS, "rev-ts": npr.lastUpdate.UnixNano()})
290 return npr
291 }
292 }
293
Stephane Barbarie40fd3b22019-04-23 21:50:47 -0400294 // Do not update the revision if data is the same
Stephane Barbariedf5479f2019-01-29 22:13:00 -0500295 if npr.Config.Data != nil && npr.Config.hashData(npr.Root, data) == npr.Config.Hash {
Stephane Barbariee0a4c792019-01-16 11:26:29 -0500296 log.Debugw("stored-data-matches-latest", log.Fields{"stored": npr.Config.Data, "provided": data})
Stephane Barbariedf5479f2019-01-29 22:13:00 -0500297 return npr
Stephane Barbariee0a4c792019-01-16 11:26:29 -0500298 }
299
Stephane Barbarie40fd3b22019-04-23 21:50:47 -0400300 // Construct a new revision based on the current one
Stephane Barbariedc5022d2018-11-19 15:21:44 -0500301 newRev := NonPersistedRevision{}
302 newRev.Config = NewDataRevision(npr.Root, data)
303 newRev.Hash = npr.Hash
Stephane Barbarie40fd3b22019-04-23 21:50:47 -0400304 newRev.Root = npr.Root
305 newRev.Name = npr.Name
Stephane Barbariedc5022d2018-11-19 15:21:44 -0500306 newRev.Branch = branch
Stephane Barbarie802aca42019-05-21 12:19:28 -0400307 newRev.lastUpdate = npr.lastUpdate
Stephane Barbariedc5022d2018-11-19 15:21:44 -0500308
309 newRev.Children = make(map[string][]Revision)
Stephane Barbarie40fd3b22019-04-23 21:50:47 -0400310 for entryName, childrenEntry := range branch.GetLatest().GetAllChildren() {
Stephane Barbariedc5022d2018-11-19 15:21:44 -0500311 newRev.Children[entryName] = append(newRev.Children[entryName], childrenEntry...)
312 }
313
Stephane Barbarie1ab43272018-12-08 21:42:13 -0500314 newRev.Finalize(false)
Stephane Barbarieec0919b2018-09-05 14:14:29 -0400315
316 return &newRev
317}
318
Stephane Barbarie40fd3b22019-04-23 21:50:47 -0400319// UpdateChildren will refresh the list of children with the provided ones
320// It will carefully go through the list and ensure that no child is lost
Stephane Barbarieef6650d2019-07-18 12:15:09 -0400321func (npr *NonPersistedRevision) UpdateChildren(ctx context.Context, name string, children []Revision, branch *Branch) Revision {
Stephane Barbariee0a4c792019-01-16 11:26:29 -0500322 npr.mutex.Lock()
323 defer npr.mutex.Unlock()
324
Stephane Barbarie40fd3b22019-04-23 21:50:47 -0400325 // Construct a new revision based on the current one
326 updatedRev := &NonPersistedRevision{}
Stephane Barbarie933b09b2019-01-09 11:12:09 -0500327 updatedRev.Config = NewDataRevision(npr.Root, npr.Config.Data)
328 updatedRev.Hash = npr.Hash
329 updatedRev.Branch = branch
Stephane Barbarie40fd3b22019-04-23 21:50:47 -0400330 updatedRev.Name = npr.Name
Stephane Barbarie802aca42019-05-21 12:19:28 -0400331 updatedRev.lastUpdate = npr.lastUpdate
Stephane Barbarie40fd3b22019-04-23 21:50:47 -0400332
333 updatedRev.Children = make(map[string][]Revision)
334 for entryName, childrenEntry := range branch.GetLatest().GetAllChildren() {
335 updatedRev.Children[entryName] = append(updatedRev.Children[entryName], childrenEntry...)
336 }
337
338 var updatedChildren []Revision
339
340 // Verify if the map contains already contains an entry matching the name value
341 // If so, we need to retain the contents of that entry and merge them with the provided children revision list
342 if existingChildren := branch.GetLatest().GetChildren(name); existingChildren != nil {
343 // Construct a map of unique child names with the respective index value
344 // for the children in the existing revision as well as the new ones
345 existingNames := make(map[string]int)
346 newNames := make(map[string]int)
347
348 for i, newChild := range children {
349 newNames[newChild.GetName()] = i
350 }
351
352 for i, existingChild := range existingChildren {
353 existingNames[existingChild.GetName()] = i
354
355 // If an existing entry is not in the new list, add it to the updated list, so it is not forgotten
356 if _, exists := newNames[existingChild.GetName()]; !exists {
357 updatedChildren = append(updatedChildren, existingChild)
358 }
359 }
360
361 log.Debugw("existing-children-names", log.Fields{"hash": npr.GetHash(), "names": existingNames})
362
363 // Merge existing and new children
364 for _, newChild := range children {
365 nameIndex, nameExists := existingNames[newChild.GetName()]
366
367 // Does the existing list contain a child with that name?
368 if nameExists {
369 // Check if the data has changed or not
370 if existingChildren[nameIndex].GetData().(proto.Message).String() != newChild.GetData().(proto.Message).String() {
Stephane Barbariec92d1072019-06-07 16:21:49 -0400371 log.Debugw("replacing-existing-child", log.Fields{
372 "old-hash": existingChildren[nameIndex].GetHash(),
373 "old-data": existingChildren[nameIndex].GetData(),
374 "new-hash": newChild.GetHash(),
375 "new-data": newChild.GetData(),
376 })
377
Stephane Barbarie40fd3b22019-04-23 21:50:47 -0400378 // replace entry
Stephane Barbarieef6650d2019-07-18 12:15:09 -0400379 newChild.GetNode().SetRoot(existingChildren[nameIndex].GetNode().GetRoot())
Stephane Barbarie40fd3b22019-04-23 21:50:47 -0400380 updatedChildren = append(updatedChildren, newChild)
381 } else {
Stephane Barbariec92d1072019-06-07 16:21:49 -0400382 log.Debugw("keeping-existing-child", log.Fields{
383 "old-hash": existingChildren[nameIndex].GetHash(),
384 "old-data": existingChildren[nameIndex].GetData(),
385 "new-hash": newChild.GetHash(),
386 "new-data": newChild.GetData(),
387 })
388
Stephane Barbarie40fd3b22019-04-23 21:50:47 -0400389 // keep existing entry
390 updatedChildren = append(updatedChildren, existingChildren[nameIndex])
391 }
392 } else {
Stephane Barbariec92d1072019-06-07 16:21:49 -0400393 log.Debugw("adding-unknown-child", log.Fields{
394 "hash": newChild.GetHash(),
395 "data": newChild.GetData(),
396 })
397
Stephane Barbarie40fd3b22019-04-23 21:50:47 -0400398 // new entry ... just add it
399 updatedChildren = append(updatedChildren, newChild)
400 }
401 }
402
403 // Save children in new revision
404 updatedRev.SetChildren(name, updatedChildren)
405
406 updatedNames := make(map[string]int)
407 for i, updatedChild := range updatedChildren {
408 updatedNames[updatedChild.GetName()] = i
409 }
410
411 log.Debugw("updated-children-names", log.Fields{"hash": npr.GetHash(), "names": updatedNames})
412
413 } else {
414 // There are no children available, just save the provided ones
415 updatedRev.SetChildren(name, children)
416 }
417
Stephane Barbarie933b09b2019-01-09 11:12:09 -0500418 updatedRev.Finalize(false)
Stephane Barbarieec0919b2018-09-05 14:14:29 -0400419
Stephane Barbariee0a4c792019-01-16 11:26:29 -0500420 return updatedRev
Stephane Barbarieec0919b2018-09-05 14:14:29 -0400421}
422
Stephane Barbarie40fd3b22019-04-23 21:50:47 -0400423// UpdateAllChildren will replace the current list of children with the provided ones
Stephane Barbarieec0919b2018-09-05 14:14:29 -0400424func (npr *NonPersistedRevision) UpdateAllChildren(children map[string][]Revision, branch *Branch) Revision {
Stephane Barbariedc5022d2018-11-19 15:21:44 -0500425 npr.mutex.Lock()
426 defer npr.mutex.Unlock()
427
Stephane Barbariec53a2752019-03-08 17:50:10 -0500428 newRev := npr
Stephane Barbariedc5022d2018-11-19 15:21:44 -0500429 newRev.Config = npr.Config
430 newRev.Hash = npr.Hash
431 newRev.Branch = branch
Stephane Barbarie40fd3b22019-04-23 21:50:47 -0400432 newRev.Name = npr.Name
Stephane Barbarie802aca42019-05-21 12:19:28 -0400433 newRev.lastUpdate = npr.lastUpdate
Stephane Barbarie40fd3b22019-04-23 21:50:47 -0400434
Stephane Barbariedc5022d2018-11-19 15:21:44 -0500435 newRev.Children = make(map[string][]Revision)
Stephane Barbariec53a2752019-03-08 17:50:10 -0500436 for entryName, childrenEntry := range children {
437 newRev.Children[entryName] = append(newRev.Children[entryName], childrenEntry...)
Stephane Barbariedc5022d2018-11-19 15:21:44 -0500438 }
Stephane Barbarie1ab43272018-12-08 21:42:13 -0500439 newRev.Finalize(false)
Stephane Barbarieec0919b2018-09-05 14:14:29 -0400440
Stephane Barbariedc5022d2018-11-19 15:21:44 -0500441 return newRev
Stephane Barbarieec0919b2018-09-05 14:14:29 -0400442}
Stephane Barbarie88fbe7f2018-09-25 12:25:23 -0400443
Stephane Barbarie40fd3b22019-04-23 21:50:47 -0400444// Drop is used to indicate when a revision is no longer required
Stephane Barbarie88fbe7f2018-09-25 12:25:23 -0400445func (npr *NonPersistedRevision) Drop(txid string, includeConfig bool) {
Stephane Barbarie7512fc82019-05-07 12:25:46 -0400446 log.Debugw("dropping-revision", log.Fields{"hash": npr.GetHash(), "name": npr.GetName()})
Stephane Barbarie40fd3b22019-04-23 21:50:47 -0400447}
Stephane Barbariedc5022d2018-11-19 15:21:44 -0500448
Stephane Barbarie40fd3b22019-04-23 21:50:47 -0400449// ChildDrop will remove a child entry matching the provided parameters from the current revision
450func (npr *NonPersistedRevision) ChildDrop(childType string, childHash string) {
451 if childType != "" {
452 children := make([]Revision, len(npr.GetChildren(childType)))
453 copy(children, npr.GetChildren(childType))
454 for i, child := range children {
455 if child.GetHash() == childHash {
456 children = append(children[:i], children[i+1:]...)
457 npr.SetChildren(childType, children)
458 break
459 }
460 }
Stephane Barbariedc5022d2018-11-19 15:21:44 -0500461 }
Stephane Barbarie88fbe7f2018-09-25 12:25:23 -0400462}
Stephane Barbarie1ab43272018-12-08 21:42:13 -0500463
Stephane Barbarie802aca42019-05-21 12:19:28 -0400464func (npr *NonPersistedRevision) SetLastUpdate(ts ...time.Time) {
465 npr.mutex.Lock()
466 defer npr.mutex.Unlock()
467
468 if ts != nil && len(ts) > 0 {
469 npr.lastUpdate = ts[0]
470 } else {
471 npr.lastUpdate = time.Now()
472 }
473}
474
475func (npr *NonPersistedRevision) GetLastUpdate() time.Time {
476 npr.mutex.RLock()
477 defer npr.mutex.RUnlock()
478
479 return npr.lastUpdate
480}
481
Stephane Barbarieef6650d2019-07-18 12:15:09 -0400482func (npr *NonPersistedRevision) LoadFromPersistence(ctx context.Context, path string, txid string, blobs map[string]*kvstore.KVPair) []Revision {
Stephane Barbariee0a4c792019-01-16 11:26:29 -0500483 // stub... required by interface
Stephane Barbarie1ab43272018-12-08 21:42:13 -0500484 return nil
485}
Stephane Barbariee0a4c792019-01-16 11:26:29 -0500486
487func (npr *NonPersistedRevision) SetupWatch(key string) {
488 // stub ... required by interface
Stephane Barbarief7fc1782019-03-28 22:33:41 -0400489}
490
Stephane Barbariec92d1072019-06-07 16:21:49 -0400491func (npr *NonPersistedRevision) StorageDrop(txid string, includeConfig bool) {
Stephane Barbarief7fc1782019-03-28 22:33:41 -0400492 // stub ... required by interface
493}
Stephane Barbarieef6650d2019-07-18 12:15:09 -0400494
495func (npr *NonPersistedRevision) getVersion() int64 {
496 return -1
497}