blob: c2a6c64054e0ec842464ce9dbda2f6ce32b6c332 [file] [log] [blame]
khenaidoobf6e7bb2018-08-14 22:27: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 */
Stephane Barbariedc5022d2018-11-19 15:21:44 -050016
Stephane Barbarie4a2564d2018-07-26 11:02:58 -040017package model
18
19import (
20 "bytes"
21 "compress/gzip"
Stephane Barbarie260a5632019-02-26 16:12:49 -050022 "encoding/hex"
Stephane Barbarie4a2564d2018-07-26 11:02:58 -040023 "github.com/golang/protobuf/proto"
Stephane Barbarie260a5632019-02-26 16:12:49 -050024 "github.com/google/uuid"
Stephane Barbarie88fbe7f2018-09-25 12:25:23 -040025 "github.com/opencord/voltha-go/common/log"
Stephane Barbariee0a4c792019-01-16 11:26:29 -050026 "github.com/opencord/voltha-go/db/kvstore"
Stephane Barbarie4a2564d2018-07-26 11:02:58 -040027 "reflect"
Stephane Barbariedc5022d2018-11-19 15:21:44 -050028 "runtime/debug"
Stephane Barbarie1ab43272018-12-08 21:42:13 -050029 "strings"
Stephane Barbariedc5022d2018-11-19 15:21:44 -050030 "sync"
Stephane Barbarie4a2564d2018-07-26 11:02:58 -040031)
32
Stephane Barbariedc5022d2018-11-19 15:21:44 -050033// PersistedRevision holds information of revision meant to be saved in a persistent storage
Stephane Barbarie4a2564d2018-07-26 11:02:58 -040034type PersistedRevision struct {
Stephane Barbarieec0919b2018-09-05 14:14:29 -040035 Revision
Stephane Barbarie4a2564d2018-07-26 11:02:58 -040036 Compress bool
Stephane Barbariee0a4c792019-01-16 11:26:29 -050037
Stephane Barbarie3cb01222019-01-16 17:15:56 -050038 events chan *kvstore.Event `json:"-"`
39 kvStore *Backend `json:"-"`
40 mutex sync.RWMutex `json:"-"`
41 isStored bool
42 isWatched bool
Stephane Barbarie4a2564d2018-07-26 11:02:58 -040043}
44
Stephane Barbariedc5022d2018-11-19 15:21:44 -050045// NewPersistedRevision creates a new instance of a PersistentRevision structure
Stephane Barbarieec0919b2018-09-05 14:14:29 -040046func NewPersistedRevision(branch *Branch, data interface{}, children map[string][]Revision) Revision {
Stephane Barbarie4a2564d2018-07-26 11:02:58 -040047 pr := &PersistedRevision{}
Stephane Barbariedc5022d2018-11-19 15:21:44 -050048 pr.kvStore = branch.Node.GetRoot().KvStore
49 pr.Revision = NewNonPersistedRevision(nil, branch, data, children)
Stephane Barbarie4a2564d2018-07-26 11:02:58 -040050 return pr
51}
52
Stephane Barbariedc5022d2018-11-19 15:21:44 -050053// Finalize is responsible of saving the revision in the persistent storage
Stephane Barbarie1ab43272018-12-08 21:42:13 -050054func (pr *PersistedRevision) Finalize(skipOnExist bool) {
55 pr.store(skipOnExist)
Stephane Barbarie4a2564d2018-07-26 11:02:58 -040056}
57
58type revData struct {
59 Children map[string][]string
60 Config string
61}
62
Stephane Barbarie1ab43272018-12-08 21:42:13 -050063func (pr *PersistedRevision) store(skipOnExist bool) {
Stephane Barbarie88fbe7f2018-09-25 12:25:23 -040064 if pr.GetBranch().Txid != "" {
65 return
66 }
Stephane Barbarie4a2564d2018-07-26 11:02:58 -040067
Stephane Barbarief7fc1782019-03-28 22:33:41 -040068 if pair, _ := pr.kvStore.Get(pr.GetName()); pair != nil && skipOnExist {
69 log.Debugw("revision-config-already-exists", log.Fields{"hash": pr.GetHash(), "name": pr.GetName()})
Stephane Barbarie4a2564d2018-07-26 11:02:58 -040070 return
71 }
Stephane Barbarie1ab43272018-12-08 21:42:13 -050072
Stephane Barbarieec0919b2018-09-05 14:14:29 -040073 if blob, err := proto.Marshal(pr.GetConfig().Data.(proto.Message)); err != nil {
Stephane Barbarie4a2564d2018-07-26 11:02:58 -040074 // TODO report error
75 } else {
76 if pr.Compress {
77 var b bytes.Buffer
78 w := gzip.NewWriter(&b)
79 w.Write(blob)
80 w.Close()
81 blob = b.Bytes()
82 }
Stephane Barbariedc5022d2018-11-19 15:21:44 -050083
Stephane Barbarief7fc1782019-03-28 22:33:41 -040084 if err := pr.kvStore.Put(pr.GetName(), blob); err != nil {
Stephane Barbariee0a4c792019-01-16 11:26:29 -050085 log.Warnw("problem-storing-revision-config",
Stephane Barbarief7fc1782019-03-28 22:33:41 -040086 log.Fields{"error": err, "hash": pr.GetHash(), "name": pr.GetName(), "data": pr.GetConfig().Data})
Stephane Barbariedc5022d2018-11-19 15:21:44 -050087 } else {
Stephane Barbarief7fc1782019-03-28 22:33:41 -040088 log.Debugw("storing-revision-config", log.Fields{"hash": pr.GetHash(), "name": pr.GetName(), "data": pr.GetConfig().Data})
Stephane Barbarie3cb01222019-01-16 17:15:56 -050089 pr.isStored = true
Stephane Barbariedc5022d2018-11-19 15:21:44 -050090 }
Stephane Barbarie4a2564d2018-07-26 11:02:58 -040091 }
92}
93
Stephane Barbariee0a4c792019-01-16 11:26:29 -050094func (pr *PersistedRevision) SetupWatch(key string) {
95 if pr.events == nil {
96 pr.events = make(chan *kvstore.Event)
97
Stephane Barbariec53a2752019-03-08 17:50:10 -050098 log.Debugw("setting-watch", log.Fields{"key": key, "revision-hash": pr.GetHash()})
Stephane Barbariee0a4c792019-01-16 11:26:29 -050099
Stephane Barbarief7fc1782019-03-28 22:33:41 -0400100 pr.SetName(key)
Stephane Barbariee0a4c792019-01-16 11:26:29 -0500101 pr.events = pr.kvStore.CreateWatch(key)
102
Stephane Barbarie3cb01222019-01-16 17:15:56 -0500103 pr.isWatched = true
104
Stephane Barbariee0a4c792019-01-16 11:26:29 -0500105 // Start watching
106 go pr.startWatching()
107 }
108}
109
Stephane Barbarie260a5632019-02-26 16:12:49 -0500110func (pr *PersistedRevision) updateInMemory(data interface{}) {
Stephane Barbariec53a2752019-03-08 17:50:10 -0500111 pr.mutex.Lock()
112 defer pr.mutex.Unlock()
113
Stephane Barbarie260a5632019-02-26 16:12:49 -0500114 var pac *proxyAccessControl
115 var pathLock string
116
117 //
118 // If a proxy exists for this revision, use it to lock access to the path
119 // and prevent simultaneous updates to the object in memory
120 //
121 if pr.GetNode().GetProxy() != nil {
Stephane Barbarie260a5632019-02-26 16:12:49 -0500122 pathLock, _ = pr.GetNode().GetProxy().parseForControlledPath(pr.GetNode().GetProxy().getFullPath())
Stephane Barbariec53a2752019-03-08 17:50:10 -0500123
124 // If the proxy already has a request in progress, then there is no need to process the watch
125 log.Debugw("update-in-memory--checking-pathlock", log.Fields{"key": pr.GetHash(), "pathLock": pathLock})
126 if PAC().IsReserved(pathLock) {
127 switch pr.GetNode().GetRoot().GetProxy().Operation {
128 case PROXY_ADD:
129 fallthrough
130 case PROXY_REMOVE:
131 fallthrough
132 case PROXY_UPDATE:
133 log.Debugw("update-in-memory--skipping", log.Fields{"key": pr.GetHash(), "path": pr.GetNode().GetProxy().getFullPath()})
134 return
135 default:
136 log.Debugw("update-in-memory--operation", log.Fields{"operation": pr.GetNode().GetRoot().GetProxy().Operation})
137 }
138 } else {
139 log.Debugw("update-in-memory--path-not-locked", log.Fields{"key": pr.GetHash(), "path": pr.GetNode().GetProxy().getFullPath()})
140 }
141
142 log.Debugw("update-in-memory--reserve-and-lock", log.Fields{"key": pr.GetHash(), "path": pathLock})
143
Stephane Barbarie260a5632019-02-26 16:12:49 -0500144 pac = PAC().ReservePath(pr.GetNode().GetProxy().getFullPath(), pr.GetNode().GetProxy(), pathLock)
145 pac.SetProxy(pr.GetNode().GetProxy())
146 pac.lock()
147
148 defer log.Debugw("update-in-memory--release-and-unlock", log.Fields{"key": pr.GetHash(), "path": pathLock})
149 defer pac.unlock()
150 defer PAC().ReleasePath(pathLock)
151 }
152
153 //
154 // Update the object in memory through a transaction
155 // This will allow for the object to be subsequently merged with any changes
156 // that might have occurred in memory
157 //
158
159 log.Debugw("update-in-memory--custom-transaction", log.Fields{"key": pr.GetHash()})
160
161 // Prepare the transaction
162 branch := pr.GetBranch()
163 latest := branch.GetLatest()
164 txidBin, _ := uuid.New().MarshalBinary()
165 txid := hex.EncodeToString(txidBin)[:12]
166
167 makeBranch := func(node *node) *Branch {
168 return node.MakeBranch(txid)
169 }
170
171 // Apply the update in a transaction branch
172 updatedRev := latest.GetNode().Update("", data, false, txid, makeBranch)
Stephane Barbarief7fc1782019-03-28 22:33:41 -0400173 updatedRev.SetName(latest.GetName())
Stephane Barbarie260a5632019-02-26 16:12:49 -0500174
175 // Merge the transaction branch in memory
176 if mergedRev, _ := latest.GetNode().MergeBranch(txid, false); mergedRev != nil {
177 branch.SetLatest(mergedRev)
178 }
Stephane Barbarie260a5632019-02-26 16:12:49 -0500179}
180
Stephane Barbariee0a4c792019-01-16 11:26:29 -0500181func (pr *PersistedRevision) startWatching() {
182 log.Debugw("starting-watch", log.Fields{"key": pr.GetHash()})
183
184StopWatchLoop:
185 for {
186 select {
187 case event, ok := <-pr.events:
188 if !ok {
Stephane Barbarief7fc1782019-03-28 22:33:41 -0400189 log.Errorw("event-channel-failure: stopping watch loop", log.Fields{"key": pr.GetHash(), "watch": pr.GetName()})
Stephane Barbariee0a4c792019-01-16 11:26:29 -0500190 break StopWatchLoop
191 }
192
Stephane Barbarief7fc1782019-03-28 22:33:41 -0400193 log.Debugw("received-event", log.Fields{"type": event.EventType, "watch": pr.GetName()})
Stephane Barbariee0a4c792019-01-16 11:26:29 -0500194
195 switch event.EventType {
196 case kvstore.DELETE:
Stephane Barbarief7fc1782019-03-28 22:33:41 -0400197 log.Debugw("delete-from-memory", log.Fields{"key": pr.GetHash(), "watch": pr.GetName()})
Stephane Barbariee0a4c792019-01-16 11:26:29 -0500198 pr.Revision.Drop("", true)
199 break StopWatchLoop
200
201 case kvstore.PUT:
Stephane Barbarief7fc1782019-03-28 22:33:41 -0400202 log.Debugw("update-in-memory", log.Fields{"key": pr.GetHash(), "watch": pr.GetName()})
Stephane Barbariee0a4c792019-01-16 11:26:29 -0500203
Stephane Barbarief7fc1782019-03-28 22:33:41 -0400204 if dataPair, err := pr.kvStore.Get(pr.GetName()); err != nil || dataPair == nil {
205 log.Errorw("update-in-memory--key-retrieval-failed", log.Fields{"key": pr.GetHash(), "watch": pr.GetName(), "error": err})
Stephane Barbariee0a4c792019-01-16 11:26:29 -0500206 } else {
Stephane Barbariedf5479f2019-01-29 22:13:00 -0500207 data := reflect.New(reflect.TypeOf(pr.GetData()).Elem())
208
209 if err := proto.Unmarshal(dataPair.Value.([]byte), data.Interface().(proto.Message)); err != nil {
Stephane Barbarief7fc1782019-03-28 22:33:41 -0400210 log.Errorw("update-in-memory--unmarshal-failed", log.Fields{"key": pr.GetHash(), "watch": pr.GetName(), "error": err})
Stephane Barbariedf5479f2019-01-29 22:13:00 -0500211 } else {
Stephane Barbarie260a5632019-02-26 16:12:49 -0500212 pr.updateInMemory(data.Interface())
Stephane Barbariedf5479f2019-01-29 22:13:00 -0500213 }
Stephane Barbariee0a4c792019-01-16 11:26:29 -0500214 }
215
216 default:
Stephane Barbarief7fc1782019-03-28 22:33:41 -0400217 log.Debugw("unhandled-event", log.Fields{"key": pr.GetHash(), "watch": pr.GetName(), "type": event.EventType})
Stephane Barbariee0a4c792019-01-16 11:26:29 -0500218 }
219 }
220 }
221
Stephane Barbarief7fc1782019-03-28 22:33:41 -0400222 log.Debugw("exiting-watch", log.Fields{"key": pr.GetHash(), "watch": pr.GetName()})
Stephane Barbariee0a4c792019-01-16 11:26:29 -0500223}
224
Stephane Barbarie1ab43272018-12-08 21:42:13 -0500225func (pr *PersistedRevision) LoadFromPersistence(path string, txid string) []Revision {
Stephane Barbariee0a4c792019-01-16 11:26:29 -0500226 log.Debugw("loading-from-persistence", log.Fields{"path": path, "txid": txid})
227
Stephane Barbarie1ab43272018-12-08 21:42:13 -0500228 var response []Revision
229 var rev Revision
Stephane Barbarie4a2564d2018-07-26 11:02:58 -0400230
Stephane Barbarie1ab43272018-12-08 21:42:13 -0500231 rev = pr
232
Stephane Barbarie260a5632019-02-26 16:12:49 -0500233 if pr.kvStore != nil && path != "" {
Stephane Barbarie1ab43272018-12-08 21:42:13 -0500234 blobMap, _ := pr.kvStore.List(path)
235
236 partition := strings.SplitN(path, "/", 2)
237 name := partition[0]
238
239 if len(partition) < 2 {
240 path = ""
Stephane Barbarie4a2564d2018-07-26 11:02:58 -0400241 } else {
Stephane Barbarie1ab43272018-12-08 21:42:13 -0500242 path = partition[1]
243 }
244
245 field := ChildrenFields(rev.GetBranch().Node.Type)[name]
246
Stephane Barbarie260a5632019-02-26 16:12:49 -0500247 if field != nil && field.IsContainer {
Stephane Barbarieaa467942019-02-06 14:09:44 -0500248 var children []Revision
249 children = make([]Revision, len(rev.GetChildren(name)))
250 copy(children, rev.GetChildren(name))
251 existChildMap := make(map[string]int)
252 for i, child := range rev.GetChildren(name) {
253 existChildMap[child.GetHash()] = i
254 }
255
Stephane Barbarie1ab43272018-12-08 21:42:13 -0500256 for _, blob := range blobMap {
257 output := blob.Value.([]byte)
258
259 data := reflect.New(field.ClassType.Elem())
260
261 if err := proto.Unmarshal(output, data.Interface().(proto.Message)); err != nil {
Stephane Barbarieaa467942019-02-06 14:09:44 -0500262 log.Errorw(
263 "loading-from-persistence--failed-to-unmarshal",
264 log.Fields{"path": path, "txid": txid, "error": err},
265 )
Stephane Barbarie11b88e72019-02-07 12:28:29 -0500266 } else if field.Key != "" {
267 var key reflect.Value
268 var keyValue interface{}
269 var keyStr string
270
Stephane Barbarie1ab43272018-12-08 21:42:13 -0500271 if path == "" {
Stephane Barbarie11b88e72019-02-07 12:28:29 -0500272 // e.g. /logical_devices --> path="" name=logical_devices key=""
273 _, key = GetAttributeValue(data.Interface(), field.Key, 0)
274 keyStr = key.String()
Stephane Barbarie1ab43272018-12-08 21:42:13 -0500275
Stephane Barbarie11b88e72019-02-07 12:28:29 -0500276 } else {
277 // e.g.
278 // /logical_devices/abcde --> path="abcde" name=logical_devices
279 // /logical_devices/abcde/image_downloads --> path="abcde/image_downloads" name=logical_devices
Stephane Barbarie1ab43272018-12-08 21:42:13 -0500280
281 partition := strings.SplitN(path, "/", 2)
282 key := partition[0]
283 if len(partition) < 2 {
284 path = ""
285 } else {
286 path = partition[1]
287 }
Stephane Barbarie11b88e72019-02-07 12:28:29 -0500288 keyValue = field.KeyFromStr(key)
289 keyStr = keyValue.(string)
Stephane Barbarie1ab43272018-12-08 21:42:13 -0500290
Stephane Barbarie11b88e72019-02-07 12:28:29 -0500291 if idx, childRev := rev.GetBranch().Node.findRevByKey(children, field.Key, keyValue); childRev != nil {
292 // Key is memory, continue recursing path
Stephane Barbarie260a5632019-02-26 16:12:49 -0500293 if newChildRev := childRev.LoadFromPersistence(path, txid); newChildRev != nil {
294 children[idx] = newChildRev[0]
Stephane Barbarie1ab43272018-12-08 21:42:13 -0500295
Stephane Barbarie260a5632019-02-26 16:12:49 -0500296 rev := rev.UpdateChildren(name, rev.GetChildren(name), rev.GetBranch())
297 rev.GetBranch().Node.makeLatest(rev.GetBranch(), rev, nil)
Stephane Barbarie1ab43272018-12-08 21:42:13 -0500298
Stephane Barbarie260a5632019-02-26 16:12:49 -0500299 response = append(response, newChildRev[0])
300 continue
301 }
Stephane Barbarie11b88e72019-02-07 12:28:29 -0500302 }
Stephane Barbarie1ab43272018-12-08 21:42:13 -0500303 }
Stephane Barbarie11b88e72019-02-07 12:28:29 -0500304
305 childRev := rev.GetBranch().Node.MakeNode(data.Interface(), txid).Latest(txid)
Stephane Barbarief7fc1782019-03-28 22:33:41 -0400306 childRev.SetName(name + "/" + keyStr)
Stephane Barbarie11b88e72019-02-07 12:28:29 -0500307
308 // Do not process a child that is already in memory
309 if _, childExists := existChildMap[childRev.GetHash()]; !childExists {
310 // Create watch for <component>/<key>
Stephane Barbarief7fc1782019-03-28 22:33:41 -0400311 childRev.SetupWatch(childRev.GetName())
Stephane Barbarie11b88e72019-02-07 12:28:29 -0500312
313 children = append(children, childRev)
314 rev = rev.UpdateChildren(name, children, rev.GetBranch())
315
316 rev.GetBranch().Node.makeLatest(rev.GetBranch(), rev, nil)
317 }
318 response = append(response, childRev)
319 continue
Stephane Barbarie1ab43272018-12-08 21:42:13 -0500320 }
Stephane Barbarie4a2564d2018-07-26 11:02:58 -0400321 }
322 }
323 }
Stephane Barbarie11b88e72019-02-07 12:28:29 -0500324
Stephane Barbarie1ab43272018-12-08 21:42:13 -0500325 return response
Stephane Barbarie4a2564d2018-07-26 11:02:58 -0400326}
Stephane Barbarieec0919b2018-09-05 14:14:29 -0400327
Stephane Barbariedc5022d2018-11-19 15:21:44 -0500328// UpdateData modifies the information in the data model and saves it in the persistent storage
Stephane Barbarieec0919b2018-09-05 14:14:29 -0400329func (pr *PersistedRevision) UpdateData(data interface{}, branch *Branch) Revision {
Stephane Barbariee0a4c792019-01-16 11:26:29 -0500330 log.Debugw("updating-persisted-data", log.Fields{"hash": pr.GetHash()})
331
Stephane Barbarieec0919b2018-09-05 14:14:29 -0400332 newNPR := pr.Revision.UpdateData(data, branch)
333
334 newPR := &PersistedRevision{
335 Revision: newNPR,
336 Compress: pr.Compress,
khenaidoob9203542018-09-17 22:56:37 -0400337 kvStore: pr.kvStore,
Stephane Barbarieec0919b2018-09-05 14:14:29 -0400338 }
339
Stephane Barbarieec0919b2018-09-05 14:14:29 -0400340 return newPR
341}
342
Stephane Barbariedc5022d2018-11-19 15:21:44 -0500343// UpdateChildren modifies the children of a revision and of a specific component and saves it in the persistent storage
Stephane Barbarieec0919b2018-09-05 14:14:29 -0400344func (pr *PersistedRevision) UpdateChildren(name string, children []Revision, branch *Branch) Revision {
Stephane Barbariee0a4c792019-01-16 11:26:29 -0500345 log.Debugw("updating-persisted-children", log.Fields{"hash": pr.GetHash()})
346
Stephane Barbarieec0919b2018-09-05 14:14:29 -0400347 newNPR := pr.Revision.UpdateChildren(name, children, branch)
348
349 newPR := &PersistedRevision{
350 Revision: newNPR,
351 Compress: pr.Compress,
khenaidoob9203542018-09-17 22:56:37 -0400352 kvStore: pr.kvStore,
Stephane Barbarieec0919b2018-09-05 14:14:29 -0400353 }
354
Stephane Barbarieec0919b2018-09-05 14:14:29 -0400355 return newPR
356}
357
Stephane Barbariedc5022d2018-11-19 15:21:44 -0500358// UpdateAllChildren modifies the children for all components of a revision and saves it in the peristent storage
Stephane Barbarieec0919b2018-09-05 14:14:29 -0400359func (pr *PersistedRevision) UpdateAllChildren(children map[string][]Revision, branch *Branch) Revision {
Stephane Barbariee0a4c792019-01-16 11:26:29 -0500360 log.Debugw("updating-all-persisted-children", log.Fields{"hash": pr.GetHash()})
361
Stephane Barbarieec0919b2018-09-05 14:14:29 -0400362 newNPR := pr.Revision.UpdateAllChildren(children, branch)
363
364 newPR := &PersistedRevision{
365 Revision: newNPR,
366 Compress: pr.Compress,
khenaidoob9203542018-09-17 22:56:37 -0400367 kvStore: pr.kvStore,
Stephane Barbarieec0919b2018-09-05 14:14:29 -0400368 }
369
Stephane Barbarieec0919b2018-09-05 14:14:29 -0400370 return newPR
371}
Stephane Barbarie88fbe7f2018-09-25 12:25:23 -0400372
373// Drop takes care of eliminating a revision hash that is no longer needed
374// and its associated config when required
375func (pr *PersistedRevision) Drop(txid string, includeConfig bool) {
Stephane Barbarief7fc1782019-03-28 22:33:41 -0400376 pr.Revision.Drop(txid, includeConfig)
377}
378
379// Drop takes care of eliminating a revision hash that is no longer needed
380// and its associated config when required
381func (pr *PersistedRevision) StorageDrop(txid string, includeConfig bool) {
Stephane Barbariee0a4c792019-01-16 11:26:29 -0500382 log.Debugw("dropping-revision",
383 log.Fields{"txid": txid, "hash": pr.GetHash(), "config-hash": pr.GetConfig().Hash, "stack": string(debug.Stack())})
384
Stephane Barbariedc5022d2018-11-19 15:21:44 -0500385 pr.mutex.Lock()
386 defer pr.mutex.Unlock()
Stephane Barbarie88fbe7f2018-09-25 12:25:23 -0400387 if pr.kvStore != nil && txid == "" {
Stephane Barbarie3cb01222019-01-16 17:15:56 -0500388 if pr.isStored {
Stephane Barbarief7fc1782019-03-28 22:33:41 -0400389 if pr.isWatched {
390 pr.kvStore.DeleteWatch(pr.GetName(), pr.events)
391 pr.isWatched = false
Stephane Barbarie3cb01222019-01-16 17:15:56 -0500392 }
393
Stephane Barbarief7fc1782019-03-28 22:33:41 -0400394 if err := pr.kvStore.Delete(pr.GetName()); err != nil {
Stephane Barbarie3cb01222019-01-16 17:15:56 -0500395 log.Errorw("failed-to-remove-revision", log.Fields{"hash": pr.GetHash(), "error": err.Error()})
396 } else {
397 pr.isStored = false
398 }
Stephane Barbarie88fbe7f2018-09-25 12:25:23 -0400399 }
400
Stephane Barbarie88fbe7f2018-09-25 12:25:23 -0400401 } else {
402 if includeConfig {
Stephane Barbariee0a4c792019-01-16 11:26:29 -0500403 log.Debugw("attempted-to-remove-transacted-revision-config", log.Fields{"hash": pr.GetConfig().Hash, "txid": txid})
Stephane Barbarie88fbe7f2018-09-25 12:25:23 -0400404 }
Stephane Barbariee0a4c792019-01-16 11:26:29 -0500405 log.Debugw("attempted-to-remove-transacted-revision", log.Fields{"hash": pr.GetHash(), "txid": txid})
Stephane Barbarie88fbe7f2018-09-25 12:25:23 -0400406 }
Stephane Barbariedc5022d2018-11-19 15:21:44 -0500407
408 pr.Revision.Drop(txid, includeConfig)
Stephane Barbarie88fbe7f2018-09-25 12:25:23 -0400409}