blob: 2066643a4a23de511aa98a7b140329ce5cb83d3c [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 (
Stephane Barbarie933b09b2019-01-09 11:12:09 -050020 "sync"
npujar9a30c702019-11-14 17:06:39 +053021
serkant.uluderya2ae470f2020-01-21 11:13:09 -080022 "github.com/opencord/voltha-lib-go/v3/pkg/log"
Stephane Barbarie933b09b2019-01-09 11:12:09 -050023)
Stephane Barbariedc5022d2018-11-19 15:21:44 -050024
Stephane Barbarie4a2564d2018-07-26 11:02:58 -040025// TODO: implement weak references or something equivalent
26// TODO: missing proper logging
27
Stephane Barbariedc5022d2018-11-19 15:21:44 -050028// Branch structure is used to classify a collection of transaction based revisions
Stephane Barbarie4a2564d2018-07-26 11:02:58 -040029type Branch struct {
Stephane Barbarieef6650d2019-07-18 12:15:09 -040030 mutex sync.RWMutex
Stephane Barbarie40fd3b22019-04-23 21:50:47 -040031 Node *node
32 Txid string
33 Origin Revision
34 Revisions map[string]Revision
35 LatestLock sync.RWMutex
36 Latest Revision
Stephane Barbarie4a2564d2018-07-26 11:02:58 -040037}
38
Stephane Barbariedc5022d2018-11-19 15:21:44 -050039// NewBranch creates a new instance of the Branch structure
Stephane Barbarie06c4a742018-10-01 11:09:32 -040040func NewBranch(node *node, txid string, origin Revision, autoPrune bool) *Branch {
Stephane Barbariedc5022d2018-11-19 15:21:44 -050041 b := &Branch{}
42 b.Node = node
43 b.Txid = txid
44 b.Origin = origin
45 b.Revisions = make(map[string]Revision)
46 b.Latest = origin
Stephane Barbarie4a2564d2018-07-26 11:02:58 -040047
Stephane Barbariedc5022d2018-11-19 15:21:44 -050048 return b
Stephane Barbarie4a2564d2018-07-26 11:02:58 -040049}
50
Stephane Barbarie40fd3b22019-04-23 21:50:47 -040051// Utility function to extract all children names for a given revision (mostly for debugging purposes)
52func (b *Branch) retrieveChildrenNames(revision Revision) []string {
53 var childrenNames []string
54
55 for _, child := range revision.GetChildren("devices") {
56 childrenNames = append(childrenNames, child.GetName())
57 }
58
59 return childrenNames
60}
61
62// Utility function to compare children names and report the missing ones (mostly for debugging purposes)
63func (b *Branch) findMissingChildrenNames(previousNames, latestNames []string) []string {
64 var missingNames []string
65
66 for _, previousName := range previousNames {
67 found := false
68
69 if len(latestNames) == 0 {
70 break
71 }
72
73 for _, latestName := range latestNames {
74 if previousName == latestName {
75 found = true
76 break
77 }
78 }
79 if !found {
80 missingNames = append(missingNames, previousName)
81 }
82 }
83
84 return missingNames
85}
86
Stephane Barbariedc5022d2018-11-19 15:21:44 -050087// SetLatest assigns the latest revision for this branch
88func (b *Branch) SetLatest(latest Revision) {
Stephane Barbarieef6650d2019-07-18 12:15:09 -040089 b.mutex.Lock()
90 defer b.mutex.Unlock()
Stephane Barbariedc5022d2018-11-19 15:21:44 -050091
Stephane Barbarie933b09b2019-01-09 11:12:09 -050092 if b.Latest != nil {
Stephane Barbarie40fd3b22019-04-23 21:50:47 -040093 log.Debugw("updating-latest-revision", log.Fields{"current": b.Latest.GetHash(), "new": latest.GetHash()})
Stephane Barbarie933b09b2019-01-09 11:12:09 -050094
Stephane Barbarie40fd3b22019-04-23 21:50:47 -040095 // Go through list of children names in current revision and new revision
96 // and then compare the resulting outputs to ensure that we have not lost any entries.
Stephane Barbarie40fd3b22019-04-23 21:50:47 -040097
Stephane Barbarie7512fc82019-05-07 12:25:46 -040098 if level, _ := log.GetPackageLogLevel(); level == log.DebugLevel {
99 var previousNames, latestNames, missingNames []string
Stephane Barbarie40fd3b22019-04-23 21:50:47 -0400100
Stephane Barbarie7512fc82019-05-07 12:25:46 -0400101 if previousNames = b.retrieveChildrenNames(b.Latest); len(previousNames) > 0 {
102 log.Debugw("children-of-previous-revision", log.Fields{"hash": b.Latest.GetHash(), "names": previousNames})
103 }
Stephane Barbarie40fd3b22019-04-23 21:50:47 -0400104
Stephane Barbarie7512fc82019-05-07 12:25:46 -0400105 if latestNames = b.retrieveChildrenNames(b.Latest); len(latestNames) > 0 {
106 log.Debugw("children-of-latest-revision", log.Fields{"hash": latest.GetHash(), "names": latestNames})
107 }
108
109 if missingNames = b.findMissingChildrenNames(previousNames, latestNames); len(missingNames) > 0 {
110 log.Debugw("children-missing-in-latest-revision", log.Fields{"hash": latest.GetHash(), "names": missingNames})
111 }
Stephane Barbarie40fd3b22019-04-23 21:50:47 -0400112 }
113
114 } else {
115 log.Debugw("setting-latest-revision", log.Fields{"new": latest.GetHash()})
116 }
Stephane Barbarie933b09b2019-01-09 11:12:09 -0500117
Stephane Barbariedc5022d2018-11-19 15:21:44 -0500118 b.Latest = latest
Stephane Barbarie4a2564d2018-07-26 11:02:58 -0400119}
Stephane Barbariedc5022d2018-11-19 15:21:44 -0500120
121// GetLatest retrieves the latest revision of the branch
122func (b *Branch) GetLatest() Revision {
Stephane Barbarieef6650d2019-07-18 12:15:09 -0400123 b.mutex.RLock()
124 defer b.mutex.RUnlock()
Stephane Barbariedc5022d2018-11-19 15:21:44 -0500125
126 return b.Latest
Stephane Barbarie4a2564d2018-07-26 11:02:58 -0400127}
Stephane Barbariedc5022d2018-11-19 15:21:44 -0500128
129// GetOrigin retrieves the original revision of the branch
130func (b *Branch) GetOrigin() Revision {
Stephane Barbarieef6650d2019-07-18 12:15:09 -0400131 b.mutex.RLock()
132 defer b.mutex.RUnlock()
Stephane Barbariedc5022d2018-11-19 15:21:44 -0500133
134 return b.Origin
135}
136
137// AddRevision inserts a new revision to the branch
138func (b *Branch) AddRevision(revision Revision) {
139 if revision != nil && b.GetRevision(revision.GetHash()) == nil {
140 b.SetRevision(revision.GetHash(), revision)
141 }
142}
143
144// GetRevision pulls a revision entry at the specified hash
145func (b *Branch) GetRevision(hash string) Revision {
Stephane Barbarieef6650d2019-07-18 12:15:09 -0400146 b.mutex.RLock()
147 defer b.mutex.RUnlock()
Stephane Barbariedc5022d2018-11-19 15:21:44 -0500148
Stephane Barbarie1039ec42019-02-04 10:43:16 -0500149 if revision, ok := b.Revisions[hash]; ok {
Stephane Barbariedc5022d2018-11-19 15:21:44 -0500150 return revision
151 }
152
153 return nil
154}
155
156// SetRevision updates a revision entry at the specified hash
157func (b *Branch) SetRevision(hash string, revision Revision) {
Stephane Barbarieef6650d2019-07-18 12:15:09 -0400158 b.mutex.Lock()
159 defer b.mutex.Unlock()
Stephane Barbariedc5022d2018-11-19 15:21:44 -0500160
161 b.Revisions[hash] = revision
Stephane Barbarie4a2564d2018-07-26 11:02:58 -0400162}
Stephane Barbarie40fd3b22019-04-23 21:50:47 -0400163
164// DeleteRevision removes a revision with the specified hash
165func (b *Branch) DeleteRevision(hash string) {
Stephane Barbarieef6650d2019-07-18 12:15:09 -0400166 b.mutex.Lock()
167 defer b.mutex.Unlock()
Stephane Barbarie40fd3b22019-04-23 21:50:47 -0400168
169 if _, ok := b.Revisions[hash]; ok {
170 delete(b.Revisions, hash)
171 }
172}