Skip to content

Commit c4bc99e

Browse files
committed
switch dictionary for mapping and location
1 parent 5335c0f commit c4bc99e

File tree

5 files changed

+352
-1
lines changed

5 files changed

+352
-1
lines changed

pdata/pprofile/location.go

Lines changed: 49 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -3,10 +3,59 @@
33

44
package pprofile // import "go.opentelemetry.io/collector/pdata/pprofile"
55

6+
import "fmt"
7+
68
// Equal checks equality with another Location
79
func (ms Location) Equal(val Location) bool {
810
return ms.MappingIndex() == val.MappingIndex() &&
911
ms.Address() == val.Address() &&
1012
ms.AttributeIndices().Equal(val.AttributeIndices()) &&
1113
ms.Line().Equal(val.Line())
1214
}
15+
16+
// switchDictionary updates the Location, switching its indices from one
17+
// dictionary to another.
18+
func (ms Location) switchDictionary(src, dst ProfilesDictionary) error {
19+
if ms.MappingIndex() > 0 {
20+
if src.MappingTable().Len() < int(ms.MappingIndex()) {
21+
return fmt.Errorf("invalid mapping index %d", ms.MappingIndex())
22+
}
23+
24+
mapping := src.MappingTable().At(int(ms.MappingIndex()))
25+
err := mapping.switchDictionary(src, dst)
26+
if err != nil {
27+
return fmt.Errorf("couldn't switch dictionary for mapping: %w", err)
28+
}
29+
idx, err := SetMapping(dst.MappingTable(), mapping)
30+
if err != nil {
31+
return fmt.Errorf("couldn't set mapping: %w", err)
32+
}
33+
ms.SetMappingIndex(idx)
34+
}
35+
36+
for i, v := range ms.AttributeIndices().All() {
37+
if src.AttributeTable().Len() < int(v) {
38+
return fmt.Errorf("invalid attribute index %d", v)
39+
}
40+
41+
attr := src.AttributeTable().At(int(v))
42+
err := attr.switchDictionary(src, dst)
43+
if err != nil {
44+
return fmt.Errorf("couldn't switch dictionary for attribute %d: %w", i, err)
45+
}
46+
idx, err := SetAttribute(dst.AttributeTable(), attr)
47+
if err != nil {
48+
return fmt.Errorf("couldn't set attribute %d: %w", i, err)
49+
}
50+
ms.AttributeIndices().SetAt(i, idx)
51+
}
52+
53+
for i, v := range ms.Line().All() {
54+
err := v.switchDictionary(src, dst)
55+
if err != nil {
56+
return fmt.Errorf("couldn't switch dictionary for line %d: %w", i, err)
57+
}
58+
}
59+
60+
return nil
61+
}

pdata/pprofile/location_test.go

Lines changed: 189 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -4,9 +4,11 @@
44
package pprofile
55

66
import (
7+
"errors"
78
"testing"
89

910
"github.com/stretchr/testify/assert"
11+
"github.com/stretchr/testify/require"
1012
)
1113

1214
func TestLocationEqual(t *testing.T) {
@@ -63,6 +65,193 @@ func TestLocationEqual(t *testing.T) {
6365
}
6466
}
6567

68+
func TestLocationSwitchDictionary(t *testing.T) {
69+
for _, tt := range []struct {
70+
name string
71+
location Location
72+
73+
src ProfilesDictionary
74+
dst ProfilesDictionary
75+
76+
wantLocation Location
77+
wantDictionary ProfilesDictionary
78+
wantErr error
79+
}{
80+
{
81+
name: "with an empty location",
82+
location: NewLocation(),
83+
84+
src: NewProfilesDictionary(),
85+
dst: NewProfilesDictionary(),
86+
87+
wantLocation: NewLocation(),
88+
wantDictionary: NewProfilesDictionary(),
89+
},
90+
{
91+
name: "with an existing mapping",
92+
location: func() Location {
93+
l := NewLocation()
94+
l.SetMappingIndex(1)
95+
return l
96+
}(),
97+
98+
src: func() ProfilesDictionary {
99+
d := NewProfilesDictionary()
100+
d.StringTable().Append("", "test")
101+
102+
d.MappingTable().AppendEmpty()
103+
m := d.MappingTable().AppendEmpty()
104+
m.SetFilenameStrindex(1)
105+
return d
106+
}(),
107+
dst: func() ProfilesDictionary {
108+
d := NewProfilesDictionary()
109+
d.StringTable().Append("", "foo")
110+
111+
d.MappingTable().AppendEmpty()
112+
d.MappingTable().AppendEmpty()
113+
return d
114+
}(),
115+
116+
wantLocation: func() Location {
117+
l := NewLocation()
118+
l.SetMappingIndex(2)
119+
return l
120+
}(),
121+
wantDictionary: func() ProfilesDictionary {
122+
d := NewProfilesDictionary()
123+
d.StringTable().Append("", "foo", "test")
124+
125+
d.MappingTable().AppendEmpty()
126+
d.MappingTable().AppendEmpty()
127+
m := d.MappingTable().AppendEmpty()
128+
m.SetFilenameStrindex(2)
129+
return d
130+
}(),
131+
},
132+
{
133+
name: "with an existing attribute",
134+
location: func() Location {
135+
l := NewLocation()
136+
l.AttributeIndices().Append(1)
137+
return l
138+
}(),
139+
140+
src: func() ProfilesDictionary {
141+
d := NewProfilesDictionary()
142+
d.StringTable().Append("", "test")
143+
144+
d.AttributeTable().AppendEmpty()
145+
a := d.AttributeTable().AppendEmpty()
146+
a.SetKeyStrindex(1)
147+
148+
return d
149+
}(),
150+
dst: func() ProfilesDictionary {
151+
d := NewProfilesDictionary()
152+
d.StringTable().Append("", "foo")
153+
154+
d.AttributeTable().AppendEmpty()
155+
d.AttributeTable().AppendEmpty()
156+
return d
157+
}(),
158+
159+
wantLocation: func() Location {
160+
l := NewLocation()
161+
l.AttributeIndices().Append(2)
162+
return l
163+
}(),
164+
wantDictionary: func() ProfilesDictionary {
165+
d := NewProfilesDictionary()
166+
d.StringTable().Append("", "foo", "test")
167+
168+
d.AttributeTable().AppendEmpty()
169+
d.AttributeTable().AppendEmpty()
170+
a := d.AttributeTable().AppendEmpty()
171+
a.SetKeyStrindex(2)
172+
return d
173+
}(),
174+
},
175+
{
176+
name: "with an attribute index that does not match anything",
177+
location: func() Location {
178+
l := NewLocation()
179+
l.AttributeIndices().Append(1)
180+
return l
181+
}(),
182+
183+
src: NewProfilesDictionary(),
184+
dst: NewProfilesDictionary(),
185+
186+
wantLocation: func() Location {
187+
l := NewLocation()
188+
l.AttributeIndices().Append(1)
189+
return l
190+
}(),
191+
wantDictionary: NewProfilesDictionary(),
192+
wantErr: errors.New("invalid attribute index 1"),
193+
},
194+
{
195+
name: "with an existing line",
196+
location: func() Location {
197+
l := NewLocation()
198+
l.Line().AppendEmpty().SetFunctionIndex(1)
199+
return l
200+
}(),
201+
202+
src: func() ProfilesDictionary {
203+
d := NewProfilesDictionary()
204+
d.StringTable().Append("", "test")
205+
206+
d.FunctionTable().AppendEmpty()
207+
f := d.FunctionTable().AppendEmpty()
208+
f.SetNameStrindex(1)
209+
210+
return d
211+
}(),
212+
dst: func() ProfilesDictionary {
213+
d := NewProfilesDictionary()
214+
d.StringTable().Append("", "foo")
215+
216+
d.FunctionTable().AppendEmpty()
217+
d.FunctionTable().AppendEmpty()
218+
return d
219+
}(),
220+
221+
wantLocation: func() Location {
222+
l := NewLocation()
223+
l.Line().AppendEmpty().SetFunctionIndex(2)
224+
return l
225+
}(),
226+
wantDictionary: func() ProfilesDictionary {
227+
d := NewProfilesDictionary()
228+
d.StringTable().Append("", "foo", "test")
229+
230+
d.FunctionTable().AppendEmpty()
231+
d.FunctionTable().AppendEmpty()
232+
f := d.FunctionTable().AppendEmpty()
233+
f.SetNameStrindex(2)
234+
return d
235+
}(),
236+
},
237+
} {
238+
t.Run(tt.name, func(t *testing.T) {
239+
l := tt.location
240+
dst := tt.dst
241+
err := l.switchDictionary(tt.src, dst)
242+
243+
if tt.wantErr == nil {
244+
require.NoError(t, err)
245+
} else {
246+
require.Equal(t, tt.wantErr, err)
247+
}
248+
249+
assert.Equal(t, tt.wantLocation, l)
250+
assert.Equal(t, tt.wantDictionary, dst)
251+
})
252+
}
253+
}
254+
66255
func buildLocation(mapIdx int32, addr uint64, attrIdxs []int32, line Line) Location {
67256
l := NewLocation()
68257
l.SetMappingIndex(mapIdx)

pdata/pprofile/mapping.go

Lines changed: 37 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -3,6 +3,8 @@
33

44
package pprofile // import "go.opentelemetry.io/collector/pdata/pprofile"
55

6+
import "fmt"
7+
68
// Equal checks equality with another Mapping
79
func (ms Mapping) Equal(val Mapping) bool {
810
return ms.MemoryStart() == val.MemoryStart() &&
@@ -11,3 +13,38 @@ func (ms Mapping) Equal(val Mapping) bool {
1113
ms.FilenameStrindex() == val.FilenameStrindex() &&
1214
ms.AttributeIndices().Equal(val.AttributeIndices())
1315
}
16+
17+
// switchDictionary updates the Mapping, switching its indices from one
18+
// dictionary to another.
19+
func (ms Mapping) switchDictionary(src, dst ProfilesDictionary) error {
20+
if ms.FilenameStrindex() > 0 {
21+
if src.StringTable().Len() < int(ms.FilenameStrindex()) {
22+
return fmt.Errorf("invalid filename index %d", ms.FilenameStrindex())
23+
}
24+
25+
idx, err := SetString(dst.StringTable(), src.StringTable().At(int(ms.FilenameStrindex())))
26+
if err != nil {
27+
return fmt.Errorf("couldn't set filename: %w", err)
28+
}
29+
ms.SetFilenameStrindex(idx)
30+
}
31+
32+
for i, v := range ms.AttributeIndices().All() {
33+
if src.AttributeTable().Len() < int(v) {
34+
return fmt.Errorf("invalid attribute index %d", v)
35+
}
36+
37+
attr := src.AttributeTable().At(int(v))
38+
err := attr.switchDictionary(src, dst)
39+
if err != nil {
40+
return fmt.Errorf("couldn't switch dictionary for attribute %d: %w", i, err)
41+
}
42+
idx, err := SetAttribute(dst.AttributeTable(), attr)
43+
if err != nil {
44+
return fmt.Errorf("couldn't set attribute %d: %w", i, err)
45+
}
46+
ms.AttributeIndices().SetAt(i, idx)
47+
}
48+
49+
return nil
50+
}

pdata/pprofile/mapping_test.go

Lines changed: 71 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -7,6 +7,7 @@ import (
77
"testing"
88

99
"github.com/stretchr/testify/assert"
10+
"github.com/stretchr/testify/require"
1011
)
1112

1213
func TestMappingEqual(t *testing.T) {
@@ -69,6 +70,76 @@ func TestMappingEqual(t *testing.T) {
6970
}
7071
}
7172

73+
func TestMappingSwitchDictionary(t *testing.T) {
74+
for _, tt := range []struct {
75+
name string
76+
mapping Mapping
77+
78+
src ProfilesDictionary
79+
dst ProfilesDictionary
80+
81+
wantMapping Mapping
82+
wantDictionary ProfilesDictionary
83+
wantErr error
84+
}{
85+
{
86+
name: "with an empty mapping",
87+
mapping: NewMapping(),
88+
89+
src: NewProfilesDictionary(),
90+
dst: NewProfilesDictionary(),
91+
92+
wantMapping: NewMapping(),
93+
wantDictionary: NewProfilesDictionary(),
94+
},
95+
{
96+
name: "with an existing filename",
97+
mapping: func() Mapping {
98+
m := NewMapping()
99+
m.SetFilenameStrindex(1)
100+
return m
101+
}(),
102+
103+
src: func() ProfilesDictionary {
104+
d := NewProfilesDictionary()
105+
d.StringTable().Append("", "test")
106+
return d
107+
}(),
108+
dst: func() ProfilesDictionary {
109+
d := NewProfilesDictionary()
110+
d.StringTable().Append("", "foo")
111+
return d
112+
}(),
113+
114+
wantMapping: func() Mapping {
115+
m := NewMapping()
116+
m.SetFilenameStrindex(2)
117+
return m
118+
}(),
119+
wantDictionary: func() ProfilesDictionary {
120+
d := NewProfilesDictionary()
121+
d.StringTable().Append("", "foo", "test")
122+
return d
123+
}(),
124+
},
125+
} {
126+
t.Run(tt.name, func(t *testing.T) {
127+
m := tt.mapping
128+
dst := tt.dst
129+
err := m.switchDictionary(tt.src, dst)
130+
131+
if tt.wantErr == nil {
132+
require.NoError(t, err)
133+
} else {
134+
require.Equal(t, tt.wantErr, err)
135+
}
136+
137+
assert.Equal(t, tt.wantMapping, m)
138+
assert.Equal(t, tt.wantDictionary, dst)
139+
})
140+
}
141+
}
142+
72143
func buildMapping(memStart, memLimit, fileOffset uint64, filenameIdx int32, attrIdxs []int32) Mapping {
73144
m := NewMapping()
74145
m.SetMemoryStart(memStart)

0 commit comments

Comments
 (0)