blob: ca89df08b4e5ef35b79fadfeef74e5b00ad5e68c [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
Stephane Barbarie933b09b2019-01-09 11:12:09 -050019import (
20 "github.com/opencord/voltha-go/common/log"
21 "sync"
22)
Stephane Barbariedc5022d2018-11-19 15:21:44 -050023
Stephane Barbarie4a2564d2018-07-26 11:02:58 -040024// TODO: implement weak references or something equivalent
25// TODO: missing proper logging
26
Stephane Barbariedc5022d2018-11-19 15:21:44 -050027// Branch structure is used to classify a collection of transaction based revisions
Stephane Barbarie4a2564d2018-07-26 11:02:58 -040028type Branch struct {
Stephane Barbariedc5022d2018-11-19 15:21:44 -050029 sync.RWMutex
Stephane Barbarie40fd3b22019-04-23 21:50:47 -040030 Node *node
31 Txid string
32 Origin Revision
33 Revisions map[string]Revision
34 LatestLock sync.RWMutex
35 Latest Revision
Stephane Barbarie4a2564d2018-07-26 11:02:58 -040036}
37
Stephane Barbariedc5022d2018-11-19 15:21:44 -050038// NewBranch creates a new instance of the Branch structure
Stephane Barbarie06c4a742018-10-01 11:09:32 -040039func NewBranch(node *node, txid string, origin Revision, autoPrune bool) *Branch {
Stephane Barbariedc5022d2018-11-19 15:21:44 -050040 b := &Branch{}
41 b.Node = node
42 b.Txid = txid
43 b.Origin = origin
44 b.Revisions = make(map[string]Revision)
45 b.Latest = origin
Stephane Barbarie4a2564d2018-07-26 11:02:58 -040046
Stephane Barbariedc5022d2018-11-19 15:21:44 -050047 return b
Stephane Barbarie4a2564d2018-07-26 11:02:58 -040048}
49
Stephane Barbarie40fd3b22019-04-23 21:50:47 -040050// Utility function to extract all children names for a given revision (mostly for debugging purposes)
51func (b *Branch) retrieveChildrenNames(revision Revision) []string {
52 var childrenNames []string
53
54 for _, child := range revision.GetChildren("devices") {
55 childrenNames = append(childrenNames, child.GetName())
56 }
57
58 return childrenNames
59}
60
61// Utility function to compare children names and report the missing ones (mostly for debugging purposes)
62func (b *Branch) findMissingChildrenNames(previousNames, latestNames []string) []string {
63 var missingNames []string
64
65 for _, previousName := range previousNames {
66 found := false
67
68 if len(latestNames) == 0 {
69 break
70 }
71
72 for _, latestName := range latestNames {
73 if previousName == latestName {
74 found = true
75 break
76 }
77 }
78 if !found {
79 missingNames = append(missingNames, previousName)
80 }
81 }
82
83 return missingNames
84}
85
Stephane Barbariedc5022d2018-11-19 15:21:44 -050086// SetLatest assigns the latest revision for this branch
87func (b *Branch) SetLatest(latest Revision) {
88 b.Lock()
89 defer b.Unlock()
90
Stephane Barbarie933b09b2019-01-09 11:12:09 -050091 if b.Latest != nil {
Stephane Barbarie40fd3b22019-04-23 21:50:47 -040092 log.Debugw("updating-latest-revision", log.Fields{"current": b.Latest.GetHash(), "new": latest.GetHash()})
Stephane Barbarie933b09b2019-01-09 11:12:09 -050093
Stephane Barbarie40fd3b22019-04-23 21:50:47 -040094 // Go through list of children names in current revision and new revision
95 // and then compare the resulting outputs to ensure that we have not lost any entries.
96 var previousNames, latestNames, missingNames []string
97
98 if previousNames = b.retrieveChildrenNames(b.Latest); len(previousNames) > 0 {
99 log.Debugw("children-of-previous-revision", log.Fields{"hash": b.Latest.GetHash(), "names": previousNames})
100 }
101
102 if latestNames = b.retrieveChildrenNames(b.Latest); len(latestNames) > 0 {
103 log.Debugw("children-of-latest-revision", log.Fields{"hash": latest.GetHash(), "names": latestNames})
104 }
105
106 if missingNames = b.findMissingChildrenNames(previousNames, latestNames); len(missingNames) > 0 {
107 log.Debugw("children-missing-in-latest-revision", log.Fields{"hash": latest.GetHash(), "names": missingNames})
108 }
109
110 } else {
111 log.Debugw("setting-latest-revision", log.Fields{"new": latest.GetHash()})
112 }
Stephane Barbarie933b09b2019-01-09 11:12:09 -0500113
Stephane Barbariedc5022d2018-11-19 15:21:44 -0500114 b.Latest = latest
Stephane Barbarie4a2564d2018-07-26 11:02:58 -0400115}
Stephane Barbariedc5022d2018-11-19 15:21:44 -0500116
117// GetLatest retrieves the latest revision of the branch
118func (b *Branch) GetLatest() Revision {
119 b.Lock()
120 defer b.Unlock()
121
122 return b.Latest
Stephane Barbarie4a2564d2018-07-26 11:02:58 -0400123}
Stephane Barbariedc5022d2018-11-19 15:21:44 -0500124
125// GetOrigin retrieves the original revision of the branch
126func (b *Branch) GetOrigin() Revision {
127 b.Lock()
128 defer b.Unlock()
129
130 return b.Origin
131}
132
133// AddRevision inserts a new revision to the branch
134func (b *Branch) AddRevision(revision Revision) {
135 if revision != nil && b.GetRevision(revision.GetHash()) == nil {
136 b.SetRevision(revision.GetHash(), revision)
137 }
138}
139
140// GetRevision pulls a revision entry at the specified hash
141func (b *Branch) GetRevision(hash string) Revision {
142 b.Lock()
143 defer b.Unlock()
144
Stephane Barbarie1039ec42019-02-04 10:43:16 -0500145 if revision, ok := b.Revisions[hash]; ok {
Stephane Barbariedc5022d2018-11-19 15:21:44 -0500146 return revision
147 }
148
149 return nil
150}
151
152// SetRevision updates a revision entry at the specified hash
153func (b *Branch) SetRevision(hash string, revision Revision) {
154 b.Lock()
155 defer b.Unlock()
156
157 b.Revisions[hash] = revision
Stephane Barbarie4a2564d2018-07-26 11:02:58 -0400158}
Stephane Barbarie40fd3b22019-04-23 21:50:47 -0400159
160// DeleteRevision removes a revision with the specified hash
161func (b *Branch) DeleteRevision(hash string) {
162 b.Lock()
163 defer b.Unlock()
164
165 if _, ok := b.Revisions[hash]; ok {
166 delete(b.Revisions, hash)
167 }
168}