-
Notifications
You must be signed in to change notification settings - Fork 536
Expand file tree
/
Copy pathpayload.go
More file actions
162 lines (136 loc) · 4.13 KB
/
Copy pathpayload.go
File metadata and controls
162 lines (136 loc) · 4.13 KB
1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
20
21
22
23
24
25
26
27
28
29
30
31
32
33
34
35
36
37
38
39
40
41
42
43
44
45
46
47
48
49
50
51
52
53
54
55
56
57
58
59
60
61
62
63
64
65
66
67
68
69
70
71
72
73
74
75
76
77
78
79
80
81
82
83
84
85
86
87
88
89
90
91
92
93
94
95
96
97
98
99
100
101
102
103
104
105
106
107
108
109
110
111
112
113
114
115
116
117
118
119
120
121
122
123
124
125
126
127
128
129
130
131
132
133
134
135
136
137
138
139
140
141
142
143
144
145
146
147
148
149
150
151
152
153
154
155
156
157
158
159
160
161
162
// Unless explicitly stated otherwise all files in this repository are licensed
// under the Apache License Version 2.0.
// This product includes software developed at Datadog (https://www.datadoghq.com/).
// Copyright 2016 Datadog, Inc.
package tracer
import (
"io"
"github.com/DataDog/dd-trace-go/v2/internal/locking"
)
// payloadStats contains the statistics of a payload.
type payloadStats struct {
size int // size in bytes
itemCount int // number of items (traces)
}
// payloadWriter defines the interface for writing data to a payload.
type payloadWriter interface {
io.Writer
push(t spanList) (stats payloadStats, err error)
grow(n int)
reset()
clear()
// recordItem records that an item was added and updates the header
recordItem()
}
// payloadReader defines the interface for reading data from a payload.
type payloadReader interface {
io.Reader
io.Closer
stats() payloadStats
size() int
itemCount() int
protocol() float64
}
// payload combines both reading and writing operations for a payload.
type payload interface {
payloadWriter
payloadReader
}
// newPayload returns a ready to use payload.
func newPayload(protocol float64) payload {
if protocol == traceProtocolV1 {
return &safePayload{
p: getPayloadV1(),
}
}
return &safePayload{
p: newPayloadV04(),
}
}
// https://github.com/msgpack/msgpack/blob/master/spec.md#array-format-family
const (
// arrays
msgpackArrayFix byte = 144 // up to 15 items
msgpackArray16 byte = 0xdc // up to 2^16-1 items, followed by size in 2 bytes
msgpackArray32 byte = 0xdd // up to 2^32-1 items, followed by size in 4 bytes
// maps
msgpackMapFix byte = 0x80 // up to 15 items
msgpackMap16 byte = 0xde // up to 2^16-1 items, followed by size in 2 bytes
msgpackMap32 byte = 0xdf // up to 2^32-1 items, followed by size in 4 bytes
)
// safePayload provides a thread-safe wrapper around payload.
type safePayload struct {
mu locking.RWMutex
p payload
}
// push pushes a new item into the stream in a thread-safe manner.
func (sp *safePayload) push(t spanList) (stats payloadStats, err error) {
sp.mu.Lock()
defer sp.mu.Unlock()
return sp.p.push(t)
}
// itemCount returns the number of items available in the stream in a thread-safe manner.
// This method is not thread-safe, but the underlying payload.itemCount() must be.
func (sp *safePayload) itemCount() int {
return sp.p.itemCount()
}
// size returns the payload size in bytes in a thread-safe manner.
func (sp *safePayload) size() int {
sp.mu.RLock()
defer sp.mu.RUnlock()
return sp.p.size()
}
// reset sets up the payload to be read a second time in a thread-safe manner.
func (sp *safePayload) reset() {
sp.mu.Lock()
defer sp.mu.Unlock()
sp.p.reset()
}
// clear empties the payload buffers in a thread-safe manner.
func (sp *safePayload) clear() {
sp.mu.Lock()
defer sp.mu.Unlock()
sp.p.clear()
}
// Read implements io.Reader in a thread-safe manner.
func (sp *safePayload) Read(b []byte) (n int, err error) {
// Note: Read modifies internal state (off, reader), so we need full lock
sp.mu.Lock()
defer sp.mu.Unlock()
return sp.p.Read(b)
}
// Close implements io.Closer in a thread-safe manner.
func (sp *safePayload) Close() error {
sp.mu.Lock()
defer sp.mu.Unlock()
return sp.p.Close()
}
// Write implements io.Writer in a thread-safe manner.
func (sp *safePayload) Write(data []byte) (n int, err error) {
sp.mu.Lock()
defer sp.mu.Unlock()
return sp.p.Write(data)
}
// grow grows the buffer to ensure it can accommodate n more bytes in a thread-safe manner.
func (sp *safePayload) grow(n int) {
sp.mu.Lock()
defer sp.mu.Unlock()
sp.p.grow(n)
}
// recordItem records that an item was added and updates the header in a thread-safe manner.
func (sp *safePayload) recordItem() {
sp.mu.Lock()
defer sp.mu.Unlock()
sp.p.recordItem()
}
// stats returns the current stats of the payload in a thread-safe manner.
func (sp *safePayload) stats() payloadStats {
sp.mu.RLock()
defer sp.mu.RUnlock()
return sp.p.stats()
}
// protocol returns the protocol version of the payload in a thread-safe manner.
func (sp *safePayload) protocol() float64 {
// Protocol is immutable after creation - no lock needed
return sp.p.protocol()
}