legacyVersion bool
}
-func (c *statSegment) getStatDirVector() unsafe.Pointer {
- dirOffset, _, _ := c.getOffsets()
- return unsafe.Pointer(&c.sharedHeader[dirOffset])
-}
-
-func (c *statSegment) getStatDirIndex(p unsafe.Pointer, index uint32) *statSegDirectoryEntry {
- return (*statSegDirectoryEntry)(unsafe.Pointer(uintptr(p) + uintptr(index)*unsafe.Sizeof(statSegDirectoryEntry{})))
-}
-
-func (c *statSegment) getHeader() (header statSegSharedHeader) {
+func (c *statSegment) getHeader() (header sharedHeader) {
if c.legacyVersion {
- return statSegHeaderLegacy(c.sharedHeader)
+ return loadSharedHeaderLegacy(c.sharedHeader)
}
- return statSegHeader(c.sharedHeader)
+ return loadSharedHeader(c.sharedHeader)
}
func (c *statSegment) getEpoch() (int64, bool) {
return fmt.Errorf("mapping shared memory failed: %v", err)
}
+ Log.Debugf("successfuly mmapped shared memory segment (size: %v) %v", size, len(data))
+
c.sharedHeader = data
c.memorySize = size
- Log.Debugf("successfuly mmapped shared memory segment (size: %v)", size)
-
- hdr := statSegHeader(c.sharedHeader)
+ hdr := loadSharedHeader(c.sharedHeader)
Log.Debugf("stat segment header: %+v", hdr)
if hdr.legacyVersion() {
c.legacyVersion = true
- hdr = statSegHeaderLegacy(c.sharedHeader)
+ hdr = loadSharedHeaderLegacy(c.sharedHeader)
Log.Debugf("falling back to legacy version (VPP <=19.04) of stat segment (header: %+v)", hdr)
}
type statDirectoryType int32
+const (
+ statDirIllegal = 0
+ statDirScalarIndex = 1
+ statDirCounterVectorSimple = 2
+ statDirCounterVectorCombined = 3
+ statDirErrorIndex = 4
+ statDirNameVector = 5
+ statDirEmpty = 6
+)
+
func (t statDirectoryType) String() string {
return adapter.StatType(t).String()
}
name [128]byte
}
+func (c *statSegment) getStatDirVector() unsafe.Pointer {
+ dirOffset, _, _ := c.getOffsets()
+ return unsafe.Pointer(&c.sharedHeader[dirOffset])
+}
+
+func (c *statSegment) getStatDirIndex(p unsafe.Pointer, index uint32) *statSegDirectoryEntry {
+ return (*statSegDirectoryEntry)(unsafe.Pointer(uintptr(p) + uintptr(index)*unsafe.Sizeof(statSegDirectoryEntry{})))
+}
+
func (c *statSegment) copyEntryData(dirEntry *statSegDirectoryEntry) adapter.Stat {
dirType := adapter.StatType(dirEntry.directoryType)
switch dirType {
- case adapter.ScalarIndex:
+ case statDirScalarIndex:
return adapter.ScalarStat(dirEntry.unionData)
- case adapter.ErrorIndex:
+ case statDirErrorIndex:
_, errOffset, _ := c.getOffsets()
offsetVector := unsafe.Pointer(&c.sharedHeader[errOffset])
val := *(*adapter.Counter)(statSegPointer(offsetVector, offset))
errData = val
} else {
- vecLen := vectorLen(offsetVector)
- for i := uint64(0); i < vecLen; i++ {
+ vecLen := uint32(vectorLen(offsetVector))
+
+ for i := uint32(0); i < vecLen; i++ {
cb := *(*uint64)(statSegPointer(offsetVector, uintptr(i)*unsafe.Sizeof(uint64(0))))
offset := uintptr(cb) + uintptr(dirEntry.unionData)*unsafe.Sizeof(adapter.Counter(0))
+ debugf("error index, cb: %d, offset: %d", cb, offset)
val := *(*adapter.Counter)(statSegPointer(unsafe.Pointer(&c.sharedHeader[0]), offset))
errData += val
}
}
return adapter.ErrorStat(errData)
- case adapter.SimpleCounterVector:
+ case statDirCounterVectorSimple:
if dirEntry.unionData == 0 {
debugf("offset invalid for %s", dirEntry.name)
break
break
}
- vecLen := vectorLen(unsafe.Pointer(&c.sharedHeader[dirEntry.unionData]))
+ vecLen := uint32(vectorLen(unsafe.Pointer(&c.sharedHeader[dirEntry.unionData])))
offsetVector := statSegPointer(unsafe.Pointer(&c.sharedHeader[0]), uintptr(dirEntry.offsetVector))
data := make([][]adapter.Counter, vecLen)
- for i := uint64(0); i < vecLen; i++ {
+ for i := uint32(0); i < vecLen; i++ {
cb := *(*uint64)(statSegPointer(offsetVector, uintptr(i)*unsafe.Sizeof(uint64(0))))
counterVec := unsafe.Pointer(&c.sharedHeader[uintptr(cb)])
- vecLen2 := vectorLen(counterVec)
+ vecLen2 := uint32(vectorLen(counterVec))
data[i] = make([]adapter.Counter, vecLen2)
- for j := uint64(0); j < vecLen2; j++ {
+ for j := uint32(0); j < vecLen2; j++ {
offset := uintptr(j) * unsafe.Sizeof(adapter.Counter(0))
val := *(*adapter.Counter)(statSegPointer(counterVec, offset))
data[i][j] = val
}
return adapter.SimpleCounterStat(data)
- case adapter.CombinedCounterVector:
+ case statDirCounterVectorCombined:
if dirEntry.unionData == 0 {
debugf("offset invalid for %s", dirEntry.name)
break
break
}
- vecLen := vectorLen(unsafe.Pointer(&c.sharedHeader[dirEntry.unionData]))
+ vecLen := uint32(vectorLen(unsafe.Pointer(&c.sharedHeader[dirEntry.unionData])))
offsetVector := statSegPointer(unsafe.Pointer(&c.sharedHeader[0]), uintptr(dirEntry.offsetVector))
data := make([][]adapter.CombinedCounter, vecLen)
- for i := uint64(0); i < vecLen; i++ {
+ for i := uint32(0); i < vecLen; i++ {
cb := *(*uint64)(statSegPointer(offsetVector, uintptr(i)*unsafe.Sizeof(uint64(0))))
counterVec := unsafe.Pointer(&c.sharedHeader[uintptr(cb)])
- vecLen2 := vectorLen(counterVec)
+ vecLen2 := uint32(vectorLen(counterVec))
data[i] = make([]adapter.CombinedCounter, vecLen2)
- for j := uint64(0); j < vecLen2; j++ {
+ for j := uint32(0); j < vecLen2; j++ {
offset := uintptr(j) * unsafe.Sizeof(adapter.CombinedCounter{})
val := *(*adapter.CombinedCounter)(statSegPointer(counterVec, offset))
data[i][j] = val
}
return adapter.CombinedCounterStat(data)
- case adapter.NameVector:
+ case statDirNameVector:
if dirEntry.unionData == 0 {
debugf("offset invalid for %s", dirEntry.name)
break
break
}
- vecLen := vectorLen(unsafe.Pointer(&c.sharedHeader[dirEntry.unionData]))
+ vecLen := uint32(vectorLen(unsafe.Pointer(&c.sharedHeader[dirEntry.unionData])))
offsetVector := statSegPointer(unsafe.Pointer(&c.sharedHeader[0]), uintptr(dirEntry.offsetVector))
data := make([]adapter.Name, vecLen)
- for i := uint64(0); i < vecLen; i++ {
+ for i := uint32(0); i < vecLen; i++ {
cb := *(*uint64)(statSegPointer(offsetVector, uintptr(i)*unsafe.Sizeof(uint64(0))))
if cb == 0 {
debugf("name vector out of range for %s (%v)", dirEntry.name, i)
continue
}
nameVec := unsafe.Pointer(&c.sharedHeader[cb])
- vecLen2 := vectorLen(nameVec)
+ vecLen2 := uint32(vectorLen(nameVec))
nameStr := make([]byte, 0, vecLen2)
- for j := uint64(0); j < vecLen2; j++ {
+ for j := uint32(0); j < vecLen2; j++ {
offset := uintptr(j) * unsafe.Sizeof(byte(0))
val := *(*byte)(statSegPointer(nameVec, offset))
if val > 0 {
}
return adapter.NameStat(data)
+ case statDirEmpty:
+ // no-op
+
default:
// TODO: monitor occurrences with metrics
debugf("Unknown type %d for stat entry: %q", dirEntry.directoryType, dirEntry.name)
}
-
return nil
}
if err != nil {
return nil, err
}
+
+ dirVector := c.getStatDirVector()
+ vecLen := uint32(vectorLen(dirVector))
+
for _, index := range indexes {
- name, err := c.entryName(index)
- if err != nil {
- return nil, err
+ if index >= vecLen {
+ return nil, fmt.Errorf("stat entry index %d out of dir vector len (%d)", index, vecLen)
}
- names = append(names, name)
+
+ dirEntry := c.getStatDirIndex(dirVector, index)
+ var name []byte
+ for n := 0; n < len(dirEntry.name); n++ {
+ if dirEntry.name[n] == 0 {
+ name = dirEntry.name[:n]
+ break
+ }
+ }
+ names = append(names, string(name))
}
if !c.accessEnd(&sa) {
return nil, adapter.ErrStatsAccessFailed
}
- dir, err := c.listIndexes(patterns...)
+ indexes, err := c.listIndexes(patterns...)
if err != nil {
return nil, err
}
- if entries, err = c.dumpEntries(dir); err != nil {
+ if entries, err = c.dumpEntries(indexes); err != nil {
return nil, err
}
func (c *StatsClient) listIndexesFunc(f func(name []byte) bool) (indexes []uint32, err error) {
if f == nil {
- // there is around ~3150 stats, so to avoid too many allocations
+ // there is around ~3157 stats, so to avoid too many allocations
// we set capacity to 3200 when listing all stats
indexes = make([]uint32, 0, 3200)
}
return indexes, nil
}
-func (c *StatsClient) entryName(index uint32) (string, error) {
+func (c *StatsClient) dumpEntries(indexes []uint32) (entries []adapter.StatEntry, err error) {
dirVector := c.getStatDirVector()
- vecLen := uint32(vectorLen(dirVector))
+ dirLen := uint32(vectorLen(dirVector))
- if index >= vecLen {
- return "", fmt.Errorf("stat entry index %d out of range (%d)", index, vecLen)
- }
-
- dirEntry := c.getStatDirIndex(dirVector, index)
-
- var name []byte
- for n := 0; n < len(dirEntry.name); n++ {
- if dirEntry.name[n] == 0 {
- name = dirEntry.name[:n]
- break
- }
- }
-
- return string(name), nil
-}
+ debugf("dumping entres for %d indexes", len(indexes))
-func (c *StatsClient) dumpEntries(indexes []uint32) (entries []adapter.StatEntry, err error) {
entries = make([]adapter.StatEntry, 0, len(indexes))
-
- dirVector := c.getStatDirVector()
-
for _, index := range indexes {
+ if index >= dirLen {
+ return nil, fmt.Errorf("stat entry index %d out of dir vector length (%d)", index, dirLen)
+ }
+
dirEntry := c.getStatDirIndex(dirVector, index)
var name []byte
break
}
}
+
+ if Debug {
+ debugf(" - %3d. dir: %q type: %v offset: %d union: %d", index, name,
+ adapter.StatType(dirEntry.directoryType), dirEntry.offsetVector, dirEntry.unionData)
+ }
+
if len(name) == 0 {
continue
}