1 // Copyright (c) 2019 Cisco and/or its affiliates.
3 // Licensed under the Apache License, Version 2.0 (the "License");
4 // you may not use this file except in compliance with the License.
5 // You may obtain a copy of the License at:
7 // http://www.apache.org/licenses/LICENSE-2.0
9 // Unless required by applicable law or agreed to in writing, software
10 // distributed under the License is distributed on an "AS IS" BASIS,
11 // WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
12 // See the License for the specific language governing permissions and
13 // limitations under the License.
22 "git.fd.io/govpp.git/adapter"
25 type statSegmentV1 struct {
30 type sharedHeaderV1 struct {
39 type statSegDirectoryEntryV1 struct {
41 // unionData can represent:
50 func newStatSegmentV1(data []byte, size int64) *statSegmentV1 {
51 return &statSegmentV1{
57 func (ss *statSegmentV1) loadSharedHeader(b []byte) (header sharedHeaderV1) {
58 h := (*sharedHeaderV1)(unsafe.Pointer(&b[0]))
59 return sharedHeaderV1{
60 version: atomic.LoadUint64(&h.version),
61 epoch: atomic.LoadInt64(&h.epoch),
62 inProgress: atomic.LoadInt64(&h.inProgress),
63 directoryOffset: atomic.LoadInt64(&h.directoryOffset),
64 errorOffset: atomic.LoadInt64(&h.errorOffset),
65 statsOffset: atomic.LoadInt64(&h.statsOffset),
69 func (ss *statSegmentV1) GetDirectoryVector() dirVector {
70 dirOffset, _, _ := ss.getOffsets()
71 return dirVector(&ss.sharedHeader[dirOffset])
74 func (ss *statSegmentV1) getErrorVector() (unsafe.Pointer, error) {
75 return nil, fmt.Errorf("error vector is not defined for stats API v1")
78 func (ss *statSegmentV1) GetStatDirOnIndex(v dirVector, index uint32) (dirSegment, dirName, dirType) {
79 statSegDir := dirSegment(uintptr(v) + uintptr(index)*unsafe.Sizeof(statSegDirectoryEntryV1{}))
80 dir := (*statSegDirectoryEntryV1)(statSegDir)
82 for n := 0; n < len(dir.name); n++ {
88 return statSegDir, dirName(name), dir.directoryType
91 func (ss *statSegmentV1) GetEpoch() (int64, bool) {
92 sh := ss.loadSharedHeader(ss.sharedHeader)
93 return sh.epoch, sh.inProgress != 0
96 func (ss *statSegmentV1) CopyEntryData(segment dirSegment, _ uint32) adapter.Stat {
97 dirEntry := (*statSegDirectoryEntryV1)(segment)
98 dirType := adapter.StatType(dirEntry.directoryType)
101 case statDirScalarIndex:
102 return adapter.ScalarStat(dirEntry.unionData)
104 case statDirErrorIndex:
105 if dirEntry.unionData == 0 {
106 debugf("offset invalid for %s", dirEntry.name)
108 } else if dirEntry.unionData >= uint64(len(ss.sharedHeader)) {
109 debugf("offset out of range for %s", dirEntry.name)
113 _, errOffset, _ := ss.getOffsets()
114 offsetVector := dirVector(&ss.sharedHeader[errOffset])
116 var errData []adapter.Counter
118 vecLen := *(*uint32)(vectorLen(offsetVector))
119 for i := uint32(0); i < vecLen; i++ {
120 cb := *(*uint64)(statSegPointer(offsetVector, uintptr(i)*unsafe.Sizeof(uint64(0))))
121 offset := uintptr(cb) + uintptr(dirEntry.unionData)*unsafe.Sizeof(adapter.Counter(0))
122 debugf("error index, cb: %d, offset: %d", cb, offset)
123 val := *(*adapter.Counter)(statSegPointer(dirVector(&ss.sharedHeader[0]), offset))
124 errData = append(errData, val)
126 return adapter.ErrorStat(errData)
128 case statDirCounterVectorSimple:
129 if dirEntry.unionData == 0 {
130 debugf("offset invalid for %s", dirEntry.name)
132 } else if dirEntry.unionData >= uint64(len(ss.sharedHeader)) {
133 debugf("offset out of range for %s", dirEntry.name)
137 vecLen := *(*uint32)(vectorLen(dirVector(&ss.sharedHeader[dirEntry.unionData])))
138 offsetVector := statSegPointer(dirVector(&ss.sharedHeader[0]), uintptr(dirEntry.offsetVector))
140 data := make([][]adapter.Counter, vecLen)
141 for i := uint32(0); i < vecLen; i++ {
142 cb := *(*uint64)(statSegPointer(offsetVector, uintptr(i)*unsafe.Sizeof(uint64(0))))
143 counterVec := dirVector(&ss.sharedHeader[uintptr(cb)])
144 vecLen2 := *(*uint32)(vectorLen(counterVec))
145 data[i] = make([]adapter.Counter, vecLen2)
146 for j := uint32(0); j < vecLen2; j++ {
147 offset := uintptr(j) * unsafe.Sizeof(adapter.Counter(0))
148 val := *(*adapter.Counter)(statSegPointer(counterVec, offset))
152 return adapter.SimpleCounterStat(data)
154 case statDirCounterVectorCombined:
155 if dirEntry.unionData == 0 {
156 debugf("offset invalid for %s", dirEntry.name)
158 } else if dirEntry.unionData >= uint64(len(ss.sharedHeader)) {
159 debugf("offset out of range for %s", dirEntry.name)
163 vecLen := *(*uint32)(vectorLen(dirVector(&ss.sharedHeader[dirEntry.unionData])))
164 offsetVector := statSegPointer(dirVector(&ss.sharedHeader[0]), uintptr(dirEntry.offsetVector))
166 data := make([][]adapter.CombinedCounter, vecLen)
167 for i := uint32(0); i < vecLen; i++ {
168 cb := *(*uint64)(statSegPointer(offsetVector, uintptr(i)*unsafe.Sizeof(uint64(0))))
169 counterVec := dirVector(&ss.sharedHeader[uintptr(cb)])
170 vecLen2 := *(*uint32)(vectorLen(counterVec))
171 data[i] = make([]adapter.CombinedCounter, vecLen2)
172 for j := uint32(0); j < vecLen2; j++ {
173 offset := uintptr(j) * unsafe.Sizeof(adapter.CombinedCounter{})
174 val := *(*adapter.CombinedCounter)(statSegPointer(counterVec, offset))
178 return adapter.CombinedCounterStat(data)
180 case statDirNameVector:
181 if dirEntry.unionData == 0 {
182 debugf("offset invalid for %s", dirEntry.name)
184 } else if dirEntry.unionData >= uint64(len(ss.sharedHeader)) {
185 debugf("offset out of range for %s", dirEntry.name)
189 vecLen := *(*uint32)(vectorLen(dirVector(&ss.sharedHeader[dirEntry.unionData])))
190 offsetVector := statSegPointer(dirVector(&ss.sharedHeader[0]), uintptr(dirEntry.offsetVector))
192 data := make([]adapter.Name, vecLen)
193 for i := uint32(0); i < vecLen; i++ {
194 cb := *(*uint64)(statSegPointer(offsetVector, uintptr(i)*unsafe.Sizeof(uint64(0))))
196 debugf("name vector out of range for %s (%v)", dirEntry.name, i)
199 nameVec := dirVector(&ss.sharedHeader[cb])
200 vecLen2 := *(*uint32)(vectorLen(nameVec))
202 nameStr := make([]byte, 0, vecLen2)
203 for j := uint32(0); j < vecLen2; j++ {
204 offset := uintptr(j) * unsafe.Sizeof(byte(0))
205 val := *(*byte)(statSegPointer(nameVec, offset))
207 nameStr = append(nameStr, val)
212 return adapter.NameStat(data)
218 debugf("Symlinks are not supported for stats v1")
221 // TODO: monitor occurrences with metrics
222 debugf("Unknown type %d for stat entry: %q", dirEntry.directoryType, dirEntry.name)
227 func (ss *statSegmentV1) UpdateEntryData(segment dirSegment, stat *adapter.Stat) error {
228 dirEntry := (*statSegDirectoryEntryV1)(segment)
229 switch (*stat).(type) {
230 case adapter.ScalarStat:
231 *stat = adapter.ScalarStat(dirEntry.unionData)
233 case adapter.ErrorStat:
234 if dirEntry.unionData == 0 {
235 debugf("offset invalid for %s", dirEntry.name)
237 } else if dirEntry.unionData >= uint64(len(ss.sharedHeader)) {
238 debugf("offset out of range for %s", dirEntry.name)
242 _, errOffset, _ := ss.getOffsets()
243 offsetVector := dirVector(&ss.sharedHeader[errOffset])
245 var errData []adapter.Counter
247 vecLen := *(*uint32)(vectorLen(dirVector(&ss.sharedHeader[errOffset])))
248 for i := uint32(0); i < vecLen; i++ {
249 cb := *(*uint64)(statSegPointer(offsetVector, uintptr(i)*unsafe.Sizeof(uint64(0))))
250 offset := uintptr(cb) + uintptr(dirEntry.unionData)*unsafe.Sizeof(adapter.Counter(0))
251 val := *(*adapter.Counter)(statSegPointer(dirVector(&ss.sharedHeader[0]), offset))
252 errData = append(errData, val)
254 *stat = adapter.ErrorStat(errData)
256 case adapter.SimpleCounterStat:
257 if dirEntry.unionData == 0 {
258 debugf("offset invalid for %s", dirEntry.name)
260 } else if dirEntry.unionData >= uint64(len(ss.sharedHeader)) {
261 debugf("offset out of range for %s", dirEntry.name)
265 vecLen := *(*uint32)(vectorLen(dirVector(&ss.sharedHeader[dirEntry.unionData])))
266 offsetVector := statSegPointer(dirVector(&ss.sharedHeader[0]), uintptr(dirEntry.offsetVector))
268 data := (*stat).(adapter.SimpleCounterStat)
269 if uint32(len(data)) != vecLen {
270 return ErrStatDataLenIncorrect
272 for i := uint32(0); i < vecLen; i++ {
273 cb := *(*uint64)(statSegPointer(offsetVector, uintptr(i)*unsafe.Sizeof(uint64(0))))
274 counterVec := dirVector(&ss.sharedHeader[uintptr(cb)])
275 vecLen2 := *(*uint32)(vectorLen(counterVec))
276 simpleData := data[i]
277 if uint32(len(simpleData)) != vecLen2 {
278 return ErrStatDataLenIncorrect
280 for j := uint32(0); j < vecLen2; j++ {
281 offset := uintptr(j) * unsafe.Sizeof(adapter.Counter(0))
282 val := *(*adapter.Counter)(statSegPointer(counterVec, offset))
287 case adapter.CombinedCounterStat:
288 if dirEntry.unionData == 0 {
289 debugf("offset invalid for %s", dirEntry.name)
291 } else if dirEntry.unionData >= uint64(len(ss.sharedHeader)) {
292 debugf("offset out of range for %s", dirEntry.name)
296 vecLen := *(*uint32)(vectorLen(dirVector(&ss.sharedHeader[dirEntry.unionData])))
297 offsetVector := statSegPointer(dirVector(&ss.sharedHeader[0]), uintptr(dirEntry.offsetVector))
299 data := (*stat).(adapter.CombinedCounterStat)
300 if uint32(len(data)) != vecLen {
301 return ErrStatDataLenIncorrect
303 for i := uint32(0); i < vecLen; i++ {
304 cb := *(*uint64)(statSegPointer(offsetVector, uintptr(i)*unsafe.Sizeof(uint64(0))))
305 counterVec := dirVector(&ss.sharedHeader[uintptr(cb)])
306 vecLen2 := *(*uint32)(vectorLen(counterVec))
308 if uint32(len(combData)) != vecLen2 {
309 return ErrStatDataLenIncorrect
311 for j := uint32(0); j < vecLen2; j++ {
312 offset := uintptr(j) * unsafe.Sizeof(adapter.CombinedCounter{})
313 val := *(*adapter.CombinedCounter)(statSegPointer(counterVec, offset))
318 case adapter.NameStat:
319 if dirEntry.unionData == 0 {
320 debugf("offset invalid for %s", dirEntry.name)
322 } else if dirEntry.unionData >= uint64(len(ss.sharedHeader)) {
323 debugf("offset out of range for %s", dirEntry.name)
327 vecLen := *(*uint32)(vectorLen(dirVector(&ss.sharedHeader[dirEntry.unionData])))
328 offsetVector := statSegPointer(dirVector(&ss.sharedHeader[0]), uintptr(dirEntry.offsetVector))
330 data := (*stat).(adapter.NameStat)
331 if uint32(len(data)) != vecLen {
332 return ErrStatDataLenIncorrect
334 for i := uint32(0); i < vecLen; i++ {
335 cb := *(*uint64)(statSegPointer(offsetVector, uintptr(i)*unsafe.Sizeof(uint64(0))))
339 nameVec := dirVector(&ss.sharedHeader[cb])
340 vecLen2 := *(*uint32)(vectorLen(nameVec))
343 if uint32(len(nameData))+1 != vecLen2 {
344 return ErrStatDataLenIncorrect
346 for j := uint32(0); j < vecLen2; j++ {
347 offset := uintptr(j) * unsafe.Sizeof(byte(0))
348 val := *(*byte)(statSegPointer(nameVec, offset))
358 Log.Debugf("Unrecognized stat type %T for stat entry: %v", stat, dirEntry.name)
364 // Get offsets for various types of data
365 func (ss *statSegmentV1) getOffsets() (dir, err, stat int64) {
366 sh := ss.loadSharedHeader(ss.sharedHeader)
367 return sh.directoryOffset, sh.errorOffset, sh.statsOffset