diff options
Diffstat (limited to 'adapter/statsclient/stat_segment_api.go')
-rw-r--r-- | adapter/statsclient/stat_segment_api.go | 137 |
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) +} |