statsclient: allow index as pattern
[govpp.git] / adapter / statsclient / statseg_v2.go
index 7091ff9..10bc5f5 100644 (file)
@@ -15,7 +15,6 @@
 package statsclient
 
 import (
-       "fmt"
        "sync/atomic"
        "unsafe"
 
@@ -37,7 +36,7 @@ type sharedHeaderV2 struct {
 }
 
 type statSegDirectoryEntryV2 struct {
-       directoryType statDirectoryType
+       directoryType dirType
        // unionData can represent:
        // - index
        // - value
@@ -65,13 +64,13 @@ func (ss *statSegmentV2) loadSharedHeader(b []byte) (header sharedHeaderV2) {
        }
 }
 
-func (ss *statSegmentV2) GetDirectoryVector() (unsafe.Pointer, error) {
+func (ss *statSegmentV2) GetDirectoryVector() dirVector {
        header := ss.loadSharedHeader(ss.sharedHeader)
-       return ss.adjust(unsafe.Pointer(&header.dirVector))
+       return ss.adjust(dirVector(&header.dirVector))
 }
 
-func (ss *statSegmentV2) GetStatDirOnIndex(p unsafe.Pointer, index uint32) (unsafe.Pointer, statDirectoryName, statDirectoryType) {
-       statSegDir := unsafe.Pointer(uintptr(p) + uintptr(index)*unsafe.Sizeof(statSegDirectoryEntryV2{}))
+func (ss *statSegmentV2) GetStatDirOnIndex(v dirVector, index uint32) (dirSegment, dirName, dirType) {
+       statSegDir := dirSegment(uintptr(v) + uintptr(index)*unsafe.Sizeof(statSegDirectoryEntryV2{}))
        dir := (*statSegDirectoryEntryV2)(statSegDir)
        var name []byte
        for n := 0; n < len(dir.name); n++ {
@@ -88,8 +87,8 @@ func (ss *statSegmentV2) GetEpoch() (int64, bool) {
        return sh.epoch, sh.inProgress != 0
 }
 
-func (ss *statSegmentV2) CopyEntryData(statSegDir unsafe.Pointer) adapter.Stat {
-       dirEntry := (*statSegDirectoryEntryV2)(statSegDir)
+func (ss *statSegmentV2) CopyEntryData(segment dirSegment) adapter.Stat {
+       dirEntry := (*statSegDirectoryEntryV2)(segment)
        if dirEntry.unionData == 0 {
                debugf("data value or pointer not defined for %s", dirEntry.name)
                return nil
@@ -100,29 +99,29 @@ func (ss *statSegmentV2) CopyEntryData(statSegDir unsafe.Pointer) adapter.Stat {
                return adapter.ScalarStat(dirEntry.unionData)
 
        case statDirErrorIndex:
-               dirVector, err := ss.getErrorVector()
-               if err != nil {
+               dirVector := ss.getErrorVector()
+               if dirVector == nil {
                        debugf("error vector pointer is out of range for %s", dirEntry.name)
                        return nil
                }
                vecLen := *(*uint32)(vectorLen(dirVector))
-               var errData adapter.Counter
+               var errData []adapter.Counter
                for i := uint32(0); i < vecLen; i++ {
                        cb := statSegPointer(dirVector, uintptr(i+1)*unsafe.Sizeof(uint64(0)))
-                       cbVal, err := ss.adjust(vectorLen(cb))
-                       if err != nil {
+                       cbVal := ss.adjust(vectorLen(cb))
+                       if cbVal == nil {
                                debugf("error counter pointer out of range")
                                continue
                        }
                        offset := uintptr(dirEntry.unionData) * unsafe.Sizeof(adapter.Counter(0))
                        val := *(*adapter.Counter)(statSegPointer(cbVal, offset))
-                       errData += val
+                       errData = append(errData, val)
                }
                return adapter.ErrorStat(errData)
 
        case statDirCounterVectorSimple:
-               dirVector, err := ss.adjust(unsafe.Pointer(&dirEntry.unionData))
-               if err != nil {
+               dirVector := ss.adjust(dirVector(&dirEntry.unionData))
+               if dirVector == nil {
                        debugf("data vector pointer is out of range for %s", dirEntry.name)
                        return nil
                }
@@ -130,8 +129,8 @@ func (ss *statSegmentV2) CopyEntryData(statSegDir unsafe.Pointer) adapter.Stat {
                data := make([][]adapter.Counter, vecLen)
                for i := uint32(0); i < vecLen; i++ {
                        counterVectorOffset := statSegPointer(dirVector, uintptr(i+1)*unsafe.Sizeof(uint64(0)))
-                       counterVector, err := ss.adjust(vectorLen(counterVectorOffset))
-                       if err != nil {
+                       counterVector := ss.adjust(vectorLen(counterVectorOffset))
+                       if counterVector == nil {
                                debugf("counter (vector simple) pointer out of range")
                                continue
                        }
@@ -146,8 +145,8 @@ func (ss *statSegmentV2) CopyEntryData(statSegDir unsafe.Pointer) adapter.Stat {
                return adapter.SimpleCounterStat(data)
 
        case statDirCounterVectorCombined:
-               dirVector, err := ss.adjust(unsafe.Pointer(&dirEntry.unionData))
-               if err != nil {
+               dirVector := ss.adjust(dirVector(&dirEntry.unionData))
+               if dirVector == nil {
                        debugf("data vector pointer is out of range for %s", dirEntry.name)
                        return nil
                }
@@ -155,8 +154,8 @@ func (ss *statSegmentV2) CopyEntryData(statSegDir unsafe.Pointer) adapter.Stat {
                data := make([][]adapter.CombinedCounter, vecLen)
                for i := uint32(0); i < vecLen; i++ {
                        counterVectorOffset := statSegPointer(dirVector, uintptr(i+1)*unsafe.Sizeof(uint64(0)))
-                       counterVector, err := ss.adjust(vectorLen(counterVectorOffset))
-                       if err != nil {
+                       counterVector := ss.adjust(vectorLen(counterVectorOffset))
+                       if counterVector == nil {
                                debugf("counter (vector combined) pointer out of range")
                                continue
                        }
@@ -171,8 +170,8 @@ func (ss *statSegmentV2) CopyEntryData(statSegDir unsafe.Pointer) adapter.Stat {
                return adapter.CombinedCounterStat(data)
 
        case statDirNameVector:
-               dirVector, err := ss.adjust(unsafe.Pointer(&dirEntry.unionData))
-               if err != nil {
+               dirVector := ss.adjust(dirVector(&dirEntry.unionData))
+               if dirVector == nil {
                        debugf("data vector pointer is out of range for %s", dirEntry.name)
                        return nil
                }
@@ -184,8 +183,8 @@ func (ss *statSegmentV2) CopyEntryData(statSegDir unsafe.Pointer) adapter.Stat {
                                debugf("name vector out of range for %s (%v)", dirEntry.name, i)
                                continue
                        }
-                       nameVector, err := ss.adjust(vectorLen(nameVectorOffset))
-                       if err != nil {
+                       nameVector := ss.adjust(vectorLen(nameVectorOffset))
+                       if nameVector == nil {
                                debugf("name data pointer out of range")
                                continue
                        }
@@ -203,6 +202,7 @@ func (ss *statSegmentV2) CopyEntryData(statSegDir unsafe.Pointer) adapter.Stat {
                return adapter.NameStat(data)
 
        case statDirEmpty:
+               return adapter.EmptyStat("<none>")
                // no-op
 
        default:
@@ -212,36 +212,36 @@ func (ss *statSegmentV2) CopyEntryData(statSegDir unsafe.Pointer) adapter.Stat {
        return nil
 }
 
-func (ss *statSegmentV2) UpdateEntryData(statSegDir unsafe.Pointer, stat *adapter.Stat) error {
-       dirEntry := (*statSegDirectoryEntryV2)(statSegDir)
+func (ss *statSegmentV2) UpdateEntryData(segment dirSegment, stat *adapter.Stat) error {
+       dirEntry := (*statSegDirectoryEntryV2)(segment)
        switch (*stat).(type) {
        case adapter.ScalarStat:
                *stat = adapter.ScalarStat(dirEntry.unionData)
 
        case adapter.ErrorStat:
-               dirVector, err := ss.getErrorVector()
-               if err != nil {
+               dirVector := ss.getErrorVector()
+               if dirVector == nil {
                        debugf("error vector pointer is out of range for %s", dirEntry.name)
                        return nil
                }
                vecLen := *(*uint32)(vectorLen(dirVector))
-               var errData adapter.Counter
+               var errData []adapter.Counter
                for i := uint32(0); i < vecLen; i++ {
                        cb := statSegPointer(dirVector, uintptr(i+1)*unsafe.Sizeof(uint64(0)))
-                       cbVal, err := ss.adjust(vectorLen(cb))
-                       if err != nil {
+                       cbVal := ss.adjust(vectorLen(cb))
+                       if cbVal == nil {
                                debugf("error counter pointer out of range")
                                continue
                        }
                        offset := uintptr(dirEntry.unionData) * unsafe.Sizeof(adapter.Counter(0))
                        val := *(*adapter.Counter)(statSegPointer(cbVal, offset))
-                       errData += val
+                       errData = append(errData, val)
                }
                *stat = adapter.ErrorStat(errData)
 
        case adapter.SimpleCounterStat:
-               dirVector, err := ss.adjust(unsafe.Pointer(&dirEntry.unionData))
-               if err != nil {
+               dirVector := ss.adjust(dirVector(&dirEntry.unionData))
+               if dirVector == nil {
                        debugf("data vector pointer is out of range for %s", dirEntry.name)
                        return nil
                }
@@ -252,8 +252,8 @@ func (ss *statSegmentV2) UpdateEntryData(statSegDir unsafe.Pointer, stat *adapte
                }
                for i := uint32(0); i < vecLen; i++ {
                        counterVectorOffset := statSegPointer(dirVector, uintptr(i+1)*unsafe.Sizeof(uint64(0)))
-                       counterVector, err := ss.adjust(vectorLen(counterVectorOffset))
-                       if err != nil {
+                       counterVector := ss.adjust(vectorLen(counterVectorOffset))
+                       if counterVector == nil {
                                debugf("counter (vector simple) pointer out of range")
                                continue
                        }
@@ -267,8 +267,8 @@ func (ss *statSegmentV2) UpdateEntryData(statSegDir unsafe.Pointer, stat *adapte
                }
 
        case adapter.CombinedCounterStat:
-               dirVector, err := ss.adjust(unsafe.Pointer(&dirEntry.unionData))
-               if err != nil {
+               dirVector := ss.adjust(dirVector(&dirEntry.unionData))
+               if dirVector == nil {
                        debugf("data vector pointer is out of range for %s", dirEntry.name)
                        return nil
                }
@@ -276,8 +276,8 @@ func (ss *statSegmentV2) UpdateEntryData(statSegDir unsafe.Pointer, stat *adapte
                data := (*stat).(adapter.CombinedCounterStat)
                for i := uint32(0); i < vecLen; i++ {
                        counterVectorOffset := statSegPointer(dirVector, uintptr(i+1)*unsafe.Sizeof(uint64(0)))
-                       counterVector, err := ss.adjust(vectorLen(counterVectorOffset))
-                       if err != nil {
+                       counterVector := ss.adjust(vectorLen(counterVectorOffset))
+                       if counterVector == nil {
                                debugf("counter (vector combined) pointer out of range")
                                continue
                        }
@@ -291,8 +291,8 @@ func (ss *statSegmentV2) UpdateEntryData(statSegDir unsafe.Pointer, stat *adapte
                }
 
        case adapter.NameStat:
-               dirVector, err := ss.adjust(unsafe.Pointer(&dirEntry.unionData))
-               if err != nil {
+               dirVector := ss.adjust(dirVector(&dirEntry.unionData))
+               if dirVector == nil {
                        debugf("data vector pointer is out of range for %s", dirEntry.name)
                        return nil
                }
@@ -304,8 +304,8 @@ func (ss *statSegmentV2) UpdateEntryData(statSegDir unsafe.Pointer, stat *adapte
                                debugf("name vector out of range for %s (%v)", dirEntry.name, i)
                                continue
                        }
-                       nameVector, err := ss.adjust(vectorLen(nameVectorOffset))
-                       if err != nil {
+                       nameVector := ss.adjust(vectorLen(nameVectorOffset))
+                       if nameVector == nil {
                                debugf("name data pointer out of range")
                                continue
                        }
@@ -334,18 +334,18 @@ func (ss *statSegmentV2) UpdateEntryData(statSegDir unsafe.Pointer, stat *adapte
 
 // Adjust data pointer using shared header and base and return
 // the pointer to a data segment
-func (ss *statSegmentV2) adjust(data unsafe.Pointer) (unsafe.Pointer, error) {
+func (ss *statSegmentV2) adjust(data dirVector) dirVector {
        header := ss.loadSharedHeader(ss.sharedHeader)
-       adjusted := unsafe.Pointer(uintptr(unsafe.Pointer(&ss.sharedHeader[0])) +
+       adjusted := dirVector(uintptr(unsafe.Pointer(&ss.sharedHeader[0])) +
                uintptr(*(*uint64)(data)) - uintptr(*(*uint64)(unsafe.Pointer(&header.base))))
        if uintptr(unsafe.Pointer(&ss.sharedHeader[len(ss.sharedHeader)-1])) <= uintptr(adjusted) ||
                uintptr(unsafe.Pointer(&ss.sharedHeader[0])) >= uintptr(adjusted) {
-               return nil, fmt.Errorf("adjusted data out of range for %v", data)
+               return nil
        }
-       return adjusted, nil
+       return adjusted
 }
 
-func (ss *statSegmentV2) getErrorVector() (unsafe.Pointer, error) {
+func (ss *statSegmentV2) getErrorVector() dirVector {
        header := ss.loadSharedHeader(ss.sharedHeader)
-       return ss.adjust(unsafe.Pointer(&header.errorVector))
+       return ss.adjust(dirVector(&header.errorVector))
 }