aboutsummaryrefslogtreecommitdiffstats
path: root/adapter/statsclient/stat_segment_api.go
diff options
context:
space:
mode:
Diffstat (limited to 'adapter/statsclient/stat_segment_api.go')
-rw-r--r--adapter/statsclient/stat_segment_api.go137
1 files changed, 137 insertions, 0 deletions
diff --git a/adapter/statsclient/stat_segment_api.go b/adapter/statsclient/stat_segment_api.go
new file mode 100644
index 0000000..2c2950f
--- /dev/null
+++ b/adapter/statsclient/stat_segment_api.go
@@ -0,0 +1,137 @@
+// Copyright (c) 2020 Cisco and/or its affiliates.
+//
+// Licensed under the Apache License, Version 2.0 (the "License");
+// you may not use this file except in compliance with the License.
+// You may obtain a copy of the License at:
+//
+// http://www.apache.org/licenses/LICENSE-2.0
+//
+// Unless required by applicable law or agreed to in writing, software
+// distributed under the License is distributed on an "AS IS" BASIS,
+// WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
+// See the License for the specific language governing permissions and
+// limitations under the License.
+
+package statsclient
+
+import (
+ "fmt"
+ "sync/atomic"
+ "time"
+ "unsafe"
+
+ "go.fd.io/govpp/adapter"
+)
+
+var (
+ // ErrStatDataLenIncorrect is returned when stat data does not match vector
+ // length of a respective data directory
+ ErrStatDataLenIncorrect = fmt.Errorf("stat data length incorrect")
+)
+
+var (
+ MaxWaitInProgress = time.Millisecond * 100
+ CheckDelayInProgress = time.Microsecond * 10
+)
+
+const (
+ minVersion = 1
+ maxVersion = 2
+)
+
+var dirTypeMapping = map[dirType]adapter.StatType{
+ 1: adapter.ScalarIndex,
+ 2: adapter.SimpleCounterVector,
+ 3: adapter.CombinedCounterVector,
+ 4: adapter.NameVector,
+ 5: adapter.Empty,
+ 6: adapter.Symlink,
+}
+
+var dirTypeMappingLegacy = map[dirType]adapter.StatType{
+ 1: adapter.ScalarIndex,
+ 2: adapter.SimpleCounterVector,
+ 3: adapter.CombinedCounterVector,
+ 4: adapter.ErrorIndex,
+ 5: adapter.NameVector,
+ 6: adapter.Empty,
+ 7: adapter.Symlink,
+}
+
+type (
+ dirVector unsafe.Pointer
+ dirSegment unsafe.Pointer
+ dirName []byte
+ dirType int32
+)
+
+// statSegment represents common API for every stats API version
+type statSegment interface {
+ // GetDirectoryVector returns pointer to memory where the beginning
+ // of the data directory is located.
+ GetDirectoryVector() dirVector
+
+ // GetStatDirOnIndex accepts directory vector and particular index.
+ // Returns pointer to the beginning of the segment. Also the directory
+ // name as [128]byte and the directory type is returned for easy use
+ // without needing to know the exact segment version.
+ //
+ // Note that if the index is equal to 0, the result pointer points to
+ // the same memory address as the argument.
+ GetStatDirOnIndex(v dirVector, index uint32) (dirSegment, dirName, adapter.StatType)
+
+ // GetEpoch re-loads stats header and returns current epoch
+ //and 'inProgress' value
+ GetEpoch() (int64, bool)
+
+ // CopyEntryData accepts pointer to a directory segment and returns adapter.Stat
+ // based on directory type populated with data. The index is an optional parameter
+ // (used by symlinks) returning stats for item on the given index only.
+ // Use ^uint32(0) as an empty index (since 0 is a valid value).
+ CopyEntryData(segment dirSegment, index uint32) adapter.Stat
+
+ // UpdateEntryData accepts pointer to a directory segment with data, and stat
+ // segment to update
+ UpdateEntryData(segment dirSegment, s *adapter.Stat) error
+}
+
+// vecHeader represents a vector header
+type vecHeader struct {
+ length uint64
+ vectorData [0]uint8
+}
+
+func getVersion(data []byte) uint64 {
+ type apiVersion struct {
+ value uint64
+ }
+ header := (*apiVersion)(unsafe.Pointer(&data[0]))
+ version := &apiVersion{
+ value: atomic.LoadUint64(&header.value),
+ }
+ debugf("stats API version loaded: %d", version.value)
+ return version.value
+}
+
+func vectorLen(v dirVector) dirVector {
+ vec := *(*vecHeader)(unsafe.Pointer(uintptr(v) - unsafe.Sizeof(uint64(0))))
+ return dirVector(&vec.length)
+}
+
+func getStatType(dirTypeNum dirType, useLegacyMapping bool) (dirTyp adapter.StatType) {
+ var exists bool
+ if useLegacyMapping {
+ dirTyp, exists = dirTypeMappingLegacy[dirTypeNum]
+ } else {
+ dirTyp, exists = dirTypeMapping[dirTypeNum]
+ }
+ if exists {
+ return dirTyp
+ }
+ return adapter.Unknown
+}
+
+//go:nosplit
+func statSegPointer(v dirVector, offset uintptr) dirVector {
+ return dirVector(uintptr(v) + offset)
+}