Improve doc & fix import ordering
[govpp.git] / adapter / statsclient / statseg.go
1 package statsclient
2
3 import (
4         "sync/atomic"
5         "time"
6         "unsafe"
7 )
8
9 var (
10         MaxWaitInProgress    = time.Millisecond * 100
11         CheckDelayInProgress = time.Microsecond * 10
12 )
13
14 type sharedHeaderBase struct {
15         epoch           int64
16         inProgress      int64
17         directoryOffset int64
18         errorOffset     int64
19         statsOffset     int64
20 }
21
22 type sharedHeaderV0 struct {
23         sharedHeaderBase
24 }
25
26 type sharedHeader struct {
27         version uint64
28         sharedHeaderBase
29 }
30
31 func (h *sharedHeader) legacyVersion() bool {
32         // older VPP (<=19.04) did not have version in stat segment header
33         // we try to provide fallback support by skipping it in header
34         if h.version > maxVersion && h.inProgress > 1 && h.epoch == 0 {
35                 return true
36         }
37         return false
38 }
39
40 func loadSharedHeader(b []byte) (header sharedHeader) {
41         h := (*sharedHeader)(unsafe.Pointer(&b[0]))
42         header.version = atomic.LoadUint64(&h.version)
43         header.epoch = atomic.LoadInt64(&h.epoch)
44         header.inProgress = atomic.LoadInt64(&h.inProgress)
45         header.directoryOffset = atomic.LoadInt64(&h.directoryOffset)
46         header.errorOffset = atomic.LoadInt64(&h.errorOffset)
47         header.statsOffset = atomic.LoadInt64(&h.statsOffset)
48         return
49 }
50
51 func loadSharedHeaderLegacy(b []byte) (header sharedHeader) {
52         h := (*sharedHeaderV0)(unsafe.Pointer(&b[0]))
53         header.version = 0
54         header.epoch = atomic.LoadInt64(&h.epoch)
55         header.inProgress = atomic.LoadInt64(&h.inProgress)
56         header.directoryOffset = atomic.LoadInt64(&h.directoryOffset)
57         header.errorOffset = atomic.LoadInt64(&h.errorOffset)
58         header.statsOffset = atomic.LoadInt64(&h.statsOffset)
59         return
60 }
61
62 type statSegAccess struct {
63         epoch int64
64 }
65
66 func (c *statSegment) accessStart() statSegAccess {
67         t := time.Now()
68
69         epoch, inprog := c.getEpoch()
70         for inprog {
71                 if time.Since(t) > MaxWaitInProgress {
72                         return statSegAccess{}
73                 } else {
74                         time.Sleep(CheckDelayInProgress)
75                 }
76                 epoch, inprog = c.getEpoch()
77         }
78         return statSegAccess{
79                 epoch: epoch,
80         }
81 }
82
83 func (c *statSegment) accessEnd(acc *statSegAccess) bool {
84         epoch, inprog := c.getEpoch()
85         if acc.epoch != epoch || inprog {
86                 return false
87         }
88         return true
89 }
90
91 type vecHeader struct {
92         length     uint64
93         vectorData [0]uint8
94 }
95
96 func vectorLen(v unsafe.Pointer) uint64 {
97         vec := *(*vecHeader)(unsafe.Pointer(uintptr(v) - unsafe.Sizeof(uint64(0))))
98         return vec.length
99 }
100
101 //go:nosplit
102 func statSegPointer(p unsafe.Pointer, offset uintptr) unsafe.Pointer {
103         return unsafe.Pointer(uintptr(p) + offset)
104 }