Skip to content

Commit 5275027

Browse files
committed
BlameConfig and MarkOwnerDelete visitors
1 parent 78df0ac commit 5275027

11 files changed

+192
-79
lines changed

pkg/datastore/datastore_rpc.go

Lines changed: 5 additions & 1 deletion
Original file line numberDiff line numberDiff line change
@@ -465,11 +465,15 @@ func (d *Datastore) BlameConfig(ctx context.Context, includeDefaults bool) (*sdc
465465
if err != nil {
466466
return nil, err
467467
}
468+
468469
// calculate the Blame
469-
bte, err := root.BlameConfig(includeDefaults)
470+
bcv := tree.NewBlameConfigVisitor(includeDefaults)
471+
err = root.Walk(ctx, bcv)
470472
if err != nil {
471473
return nil, err
472474
}
475+
bte := bcv.GetResult()
476+
473477
// set the root level elements name to the target name
474478
bte.Name = d.config.Name
475479
return bte, nil

pkg/datastore/transaction_rpc.go

Lines changed: 5 additions & 1 deletion
Original file line numberDiff line numberDiff line change
@@ -209,7 +209,11 @@ func (d *Datastore) lowlevelTransactionSet(ctx context.Context, transaction *typ
209209

210210
oldIntentContent := lvs.ToUpdateSlice()
211211

212-
root.MarkOwnerDelete(intent.GetName(), intent.GetOnlyIntended())
212+
marksOwnerDeleteVisitor := tree.NewMarkOwnerDeleteVisitor(intent.GetName(), intent.GetOnlyIntended())
213+
err := root.Walk(ctx, marksOwnerDeleteVisitor)
214+
if err != nil {
215+
return nil, err
216+
}
213217

214218
// store the old intent content in the transaction as the old intent.
215219
err = transaction.AddIntentContent(intent.GetName(), types.TransactionIntentOld, oldIntentContent.GetFirstPriorityValue(), oldIntentContent)

pkg/datastore/tree_operation_test.go

Lines changed: 5 additions & 1 deletion
Original file line numberDiff line numberDiff line change
@@ -807,7 +807,11 @@ func TestDatastore_populateTree(t *testing.T) {
807807
t.Error(err)
808808
}
809809

810-
root.MarkOwnerDelete(tt.intentName, false)
810+
marksOwnerDeleteVisitor := tree.NewMarkOwnerDeleteVisitor(tt.intentName, false)
811+
err = root.Walk(ctx, marksOwnerDeleteVisitor)
812+
if err != nil {
813+
t.Error(err)
814+
}
811815

812816
newFlag := types.NewUpdateInsertFlags().SetNewFlag()
813817

pkg/tree/entry.go

Lines changed: 16 additions & 3 deletions
Original file line numberDiff line numberDiff line change
@@ -70,8 +70,8 @@ type Entry interface {
7070
getHighestPrecedenceLeafValue(context.Context) (*LeafEntry, error)
7171
// GetByOwner returns the branches Updates by owner
7272
GetByOwner(owner string, result []*LeafEntry) LeafVariantSlice
73-
// markOwnerDelete Sets the delete flag on all the LeafEntries belonging to the given owner.
74-
MarkOwnerDelete(o string, onlyIntended bool)
73+
// // markOwnerDelete Sets the delete flag on all the LeafEntries belonging to the given owner.
74+
// MarkOwnerDelete(o string, onlyIntended bool)
7575
// GetDeletes returns the cache-updates that are not updated, have no lower priority value left and hence should be deleted completely
7676
GetDeletes(entries []types.DeleteEntry, aggregatePaths bool) ([]types.DeleteEntry, error)
7777
// Walk takes the EntryVisitor and applies it to every Entry in the tree
@@ -154,12 +154,25 @@ type Entry interface {
154154
GetListChilds() ([]Entry, error)
155155
BreadthSearch(ctx context.Context, path string) ([]Entry, error)
156156
DeepCopy(tc *TreeContext, parent Entry) (Entry, error)
157-
BlameConfig(includeDefaults bool) (*sdcpb.BlameTreeElement, error)
158157
canDeleteBranch(keepDefault bool) bool
159158
deleteCanDeleteChilds(keepDefault bool)
159+
GetLeafVariantEntries() LeafVariantEntries
160160
}
161161

162162
type EntryVisitor interface {
163163
Visit(ctx context.Context, s *sharedEntryAttributes) error
164164
Up()
165165
}
166+
167+
type LeafVariantEntry interface {
168+
MarkDelete(onlyIntended bool)
169+
GetEntry() Entry
170+
String() string
171+
}
172+
173+
type LeafVariantEntries interface {
174+
MarkOwnerForDeletion(owner string, onlyIntended bool) *LeafEntry
175+
GetHighestPrecedence(onlyNewOrUpdated bool, includeDefaults bool) *LeafEntry
176+
GetRunning() *LeafEntry
177+
DeleteByOwner(owner string) *LeafEntry
178+
}

pkg/tree/entry_test.go

Lines changed: 15 additions & 3 deletions
Original file line numberDiff line numberDiff line change
@@ -306,7 +306,11 @@ func Test_Entry_Three(t *testing.T) {
306306

307307
// indicate that the intent is receiving an update
308308
// therefor invalidate all the present entries of the owner / intent
309-
root.MarkOwnerDelete(owner1, false)
309+
marksOwnerDeleteVisitor := NewMarkOwnerDeleteVisitor(owner1, false)
310+
err = root.Walk(ctx, marksOwnerDeleteVisitor)
311+
if err != nil {
312+
t.Error(err)
313+
}
310314

311315
// add incomming set intent reques data
312316
overwriteDesc := testhelper.GetStringTvProto("Owerwrite Description")
@@ -425,7 +429,11 @@ func Test_Entry_Four(t *testing.T) {
425429

426430
// indicate that the intent is receiving an update
427431
// therefor invalidate all the present entries of the owner / intent
428-
root.MarkOwnerDelete(owner1, false)
432+
marksOwnerDeleteVisitor := NewMarkOwnerDeleteVisitor(owner1, false)
433+
err = root.Walk(ctx, marksOwnerDeleteVisitor)
434+
if err != nil {
435+
t.Error(err)
436+
}
429437

430438
// add incomming set intent reques data
431439
overwriteDesc := testhelper.GetStringTvProto("Owerwrite Description")
@@ -667,7 +675,11 @@ func Test_Entry_Delete_Aggregation(t *testing.T) {
667675
}
668676

669677
// get ready to add the new intent data
670-
root.MarkOwnerDelete(owner1, false)
678+
marksOwnerDeleteVisitor := NewMarkOwnerDeleteVisitor(owner1, false)
679+
err = root.Walk(ctx, marksOwnerDeleteVisitor)
680+
if err != nil {
681+
t.Error(err)
682+
}
671683

672684
u1n := types.NewUpdate([]string{"interface", "ethernet-1/1", "description"}, desc3, prio50, owner1, ts1)
673685
u2n := types.NewUpdate([]string{"interface", "ethernet-1/1", "name"}, testhelper.GetStringTvProto("ethernet-1/1"), prio50, owner1, ts1)

pkg/tree/leaf_variants.go

Lines changed: 7 additions & 4 deletions
Original file line numberDiff line numberDiff line change
@@ -11,15 +11,15 @@ import (
1111
)
1212

1313
type LeafVariants struct {
14-
les []*LeafEntry
14+
les LeafVariantSlice
1515
lesMutex sync.RWMutex
1616
tc *TreeContext
1717
parentEntry Entry
1818
}
1919

2020
func newLeafVariants(tc *TreeContext, parentEnty Entry) *LeafVariants {
2121
return &LeafVariants{
22-
les: make([]*LeafEntry, 0, 2),
22+
les: make(LeafVariantSlice, 0, 2),
2323
tc: tc,
2424
parentEntry: parentEnty,
2525
}
@@ -317,12 +317,15 @@ func (lv *LeafVariants) GetByOwner(owner string) *LeafEntry {
317317
}
318318

319319
// MarkOwnerForDeletion searches for a LefVariant of given owner, if it exists
320-
// the entry is marked for deletion
321-
func (lv *LeafVariants) MarkOwnerForDeletion(owner string, onlyIntended bool) {
320+
// the entry is marked for deletion.
321+
// returning true if an owner entry was found, false if not
322+
func (lv *LeafVariants) MarkOwnerForDeletion(owner string, onlyIntended bool) *LeafEntry {
322323
le := lv.GetByOwner(owner)
323324
if le != nil {
324325
le.MarkDelete(onlyIntended)
326+
return le
325327
}
328+
return nil
326329
}
327330

328331
func (lv *LeafVariants) DeleteByOwner(owner string) {

pkg/tree/sharedEntryAttributes.go

Lines changed: 8 additions & 61 deletions
Original file line numberDiff line numberDiff line change
@@ -18,7 +18,6 @@ import (
1818
"github.com/sdcio/data-server/pkg/utils"
1919
sdcpb "github.com/sdcio/sdc-protos/sdcpb"
2020
log "github.com/sirupsen/logrus"
21-
"google.golang.org/protobuf/proto"
2221
"google.golang.org/protobuf/types/known/emptypb"
2322
)
2423

@@ -111,7 +110,7 @@ func newSharedEntryAttributes(ctx context.Context, parent Entry, pathElemName st
111110
}
112111

113112
func (s *sharedEntryAttributes) GetRoot() Entry {
114-
if s.parent == nil {
113+
if s.IsRoot() {
115114
return s
116115
}
117116
return s.parent.GetRoot()
@@ -410,7 +409,7 @@ func (s *sharedEntryAttributes) GetLevel() int {
410409
return *s.level
411410
}
412411
// if we're at the root level, return 0
413-
if s.parent == nil {
412+
if s.IsRoot() {
414413
return 0
415414
}
416415
// Get parent level and add 1
@@ -673,7 +672,7 @@ func (s *sharedEntryAttributes) GetDeletes(deletes []types.DeleteEntry, aggregat
673672
// the level of recursion is indicated via the levelUp attribute
674673
func (s *sharedEntryAttributes) GetFirstAncestorWithSchema() (Entry, int) {
675674
// if root node is reached
676-
if s.parent == nil {
675+
if s.IsRoot() {
677676
return nil, 0
678677
}
679678
// check if the parent has a schema
@@ -705,7 +704,7 @@ func (s *sharedEntryAttributes) GetByOwner(owner string, result []*LeafEntry) Le
705704
// Path returns the root based path of the Entry
706705
func (s *sharedEntryAttributes) Path() types.PathSlice {
707706
// special handling for root node
708-
if s.parent == nil {
707+
if s.IsRoot() {
709708
return types.PathSlice{}
710709
}
711710
return append(s.parent.Path(), s.pathElemName)
@@ -942,7 +941,6 @@ func (s *sharedEntryAttributes) getHighestPrecedenceLeafValue(ctx context.Contex
942941
}
943942

944943
func (s *sharedEntryAttributes) GetRootBasedEntryChain() []Entry {
945-
s.GetLevel()
946944
if s.IsRoot() {
947945
return []Entry{}
948946
}
@@ -1550,15 +1548,6 @@ func (s *sharedEntryAttributes) StringIndent(result []string) []string {
15501548
return result
15511549
}
15521550

1553-
// markOwnerDelete Sets the delete flag on all the LeafEntries belonging to the given owner.
1554-
func (s *sharedEntryAttributes) MarkOwnerDelete(o string, onlyIntended bool) {
1555-
s.leafVariants.MarkOwnerForDeletion(o, onlyIntended)
1556-
// recurse into childs
1557-
for _, child := range s.childs.GetAll() {
1558-
child.MarkOwnerDelete(o, onlyIntended)
1559-
}
1560-
}
1561-
15621551
// SdcpbPath returns the sdcpb.Path, with its elements and keys based on the local schema
15631552
func (s *sharedEntryAttributes) SdcpbPath() (*sdcpb.Path, error) {
15641553
return s.SdcpbPathInternal(s.Path())
@@ -1669,52 +1658,6 @@ func (s *sharedEntryAttributes) TreeExport(owner string) ([]*tree_persist.TreeEl
16691658
return nil, nil
16701659
}
16711660

1672-
func (s *sharedEntryAttributes) BlameConfig(includeDefaults bool) (*sdcpb.BlameTreeElement, error) {
1673-
name := s.pathElemName
1674-
if s.GetLevel() == 0 {
1675-
name = "root"
1676-
}
1677-
result := sdcpb.NewBlameTreeElement(name)
1678-
1679-
// process Value
1680-
highestLe := s.leafVariants.GetHighestPrecedence(false, true)
1681-
if highestLe != nil {
1682-
if highestLe.Update.Owner() != DefaultsIntentName || includeDefaults {
1683-
result.SetValue(highestLe.Update.Value()).SetOwner(highestLe.Update.Owner())
1684-
1685-
// check if running equals the expected
1686-
runningLe := s.leafVariants.GetRunning()
1687-
if runningLe != nil {
1688-
if !proto.Equal(runningLe.Update.Value(), highestLe.Update.Value()) {
1689-
result.DeviationValue = runningLe.Value()
1690-
}
1691-
}
1692-
} else {
1693-
// if it is default but no default is meant to be returned
1694-
return nil, nil
1695-
}
1696-
}
1697-
1698-
// process Childs
1699-
for _, c := range s.filterActiveChoiceCaseChilds() {
1700-
childBlame, err := c.BlameConfig(includeDefaults)
1701-
if err != nil {
1702-
return nil, err
1703-
}
1704-
// if it is not meant to be added we will get nil, so check and skip in case
1705-
if childBlame != nil {
1706-
result.AddChild(childBlame)
1707-
}
1708-
}
1709-
1710-
// sort to make te output stable
1711-
slices.SortFunc(result.Childs, func(a *sdcpb.BlameTreeElement, b *sdcpb.BlameTreeElement) int {
1712-
return strings.Compare(a.GetName(), b.GetName())
1713-
})
1714-
1715-
return result, nil
1716-
}
1717-
17181661
// getKeyName checks if s is a key level element in the tree, if not an error is throw
17191662
// if it is a key level element, the name of the key is determined via the ancestor schemas
17201663
func (s *sharedEntryAttributes) getKeyName() (string, error) {
@@ -1822,3 +1765,7 @@ func (s *sharedEntryAttributes) containsOnlyDefaults() bool {
18221765

18231766
return true
18241767
}
1768+
1769+
func (s *sharedEntryAttributes) GetLeafVariantEntries() LeafVariantEntries {
1770+
return s.leafVariants
1771+
}

pkg/tree/sharedEntryAttributes_test.go

Lines changed: 10 additions & 2 deletions
Original file line numberDiff line numberDiff line change
@@ -886,11 +886,15 @@ func Test_sharedEntryAttributes_BlameConfig(t *testing.T) {
886886
for _, tt := range tests {
887887
t.Run(tt.name, func(t *testing.T) {
888888
s := tt.r(t)
889-
got, err := s.BlameConfig(tt.includeDefaults)
889+
890+
bcv := NewBlameConfigVisitor(tt.includeDefaults)
891+
err := s.Walk(ctx, bcv)
892+
890893
if (err != nil) != tt.wantErr {
891894
t.Errorf("sharedEntryAttributes.BlameConfig() error = %v, wantErr %v", err, tt.wantErr)
892895
return
893896
}
897+
got := bcv.GetResult()
894898

895899
// // generate the want part via
896900
// // ---------------------------------------
@@ -1004,7 +1008,11 @@ func Test_sharedEntryAttributes_ReApply(t *testing.T) {
10041008
}
10051009

10061010
// mark owner delete
1007-
newRoot.MarkOwnerDelete(owner1, false)
1011+
marksOwnerDeleteVisitor := NewMarkOwnerDeleteVisitor(owner1, false)
1012+
err = root.Walk(ctx, marksOwnerDeleteVisitor)
1013+
if err != nil {
1014+
t.Error(err)
1015+
}
10081016

10091017
err = newRoot.AddUpdatesRecursive(ctx, updSlice, flagsNew)
10101018
if err != nil {

pkg/tree/visitor_blame_config.go

Lines changed: 76 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,76 @@
1+
package tree
2+
3+
import (
4+
"context"
5+
"slices"
6+
"strings"
7+
8+
sdcpb "github.com/sdcio/sdc-protos/sdcpb"
9+
"google.golang.org/protobuf/proto"
10+
)
11+
12+
type BlameConfigVisitor struct {
13+
stack []*sdcpb.BlameTreeElement
14+
includeDefaults bool
15+
// skipUp bool
16+
}
17+
18+
func NewBlameConfigVisitor(includeDefaults bool) *BlameConfigVisitor {
19+
return &BlameConfigVisitor{
20+
stack: []*sdcpb.BlameTreeElement{},
21+
includeDefaults: includeDefaults,
22+
}
23+
}
24+
25+
func (b *BlameConfigVisitor) Visit(ctx context.Context, s *sharedEntryAttributes) error {
26+
name := s.pathElemName
27+
if s.IsRoot() {
28+
name = "root"
29+
}
30+
result := sdcpb.NewBlameTreeElement(name)
31+
skipAdd := false
32+
33+
// process Value
34+
highestLe := s.GetLeafVariantEntries().GetHighestPrecedence(false, true)
35+
if highestLe != nil {
36+
if highestLe.Update.Owner() != DefaultsIntentName || b.includeDefaults {
37+
result.SetValue(highestLe.Update.Value()).SetOwner(highestLe.Update.Owner())
38+
39+
// check if running equals the expected
40+
runningLe := s.GetLeafVariantEntries().GetRunning()
41+
if runningLe != nil {
42+
if !proto.Equal(runningLe.Update.Value(), highestLe.Update.Value()) {
43+
result.DeviationValue = runningLe.Value()
44+
}
45+
}
46+
} else {
47+
// if it is default but no default is meant to be returned
48+
skipAdd = true
49+
}
50+
}
51+
// add to the result tree as a child
52+
if !skipAdd && len(b.stack) > 0 {
53+
b.stack[len(b.stack)-1].AddChild(result)
54+
}
55+
// add to the stack as last element
56+
b.stack = append(b.stack, result)
57+
return nil
58+
}
59+
60+
func (b *BlameConfigVisitor) Up() {
61+
// sort to make te output stable
62+
slices.SortFunc(b.stack[len(b.stack)-1].Childs, func(a *sdcpb.BlameTreeElement, b *sdcpb.BlameTreeElement) int {
63+
return strings.Compare(a.GetName(), b.GetName())
64+
})
65+
// remove the last elem from stack
66+
if len(b.stack) > 1 {
67+
b.stack = b.stack[:len(b.stack)-1]
68+
}
69+
}
70+
71+
func (b *BlameConfigVisitor) GetResult() *sdcpb.BlameTreeElement {
72+
if len(b.stack) == 1 {
73+
return b.stack[0]
74+
}
75+
return nil
76+
}

0 commit comments

Comments
 (0)