-
Notifications
You must be signed in to change notification settings - Fork 0
/
Copy pathtrace.go
287 lines (242 loc) · 7.38 KB
/
trace.go
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
163
164
165
166
167
168
169
170
171
172
173
174
175
176
177
178
179
180
181
182
183
184
185
186
187
188
189
190
191
192
193
194
195
196
197
198
199
200
201
202
203
204
205
206
207
208
209
210
211
212
213
214
215
216
217
218
219
220
221
222
223
224
225
226
227
228
229
230
231
232
233
234
235
236
237
238
239
240
241
242
243
244
245
246
247
248
249
250
251
252
253
254
255
256
257
258
259
260
261
262
263
264
265
266
267
268
269
270
271
272
273
274
275
276
277
278
279
280
281
282
283
284
285
package mrnes
import (
"encoding/json"
"github.com/iti/evt/vrtime"
"gopkg.in/yaml.v3"
"os"
"path"
"strconv"
"sort"
)
type TraceRecordType int
const (
NetworkType TraceRecordType = iota
CmpPtnType
)
var trtToStr map[TraceRecordType]string = map[TraceRecordType]string{NetworkType: "network", CmpPtnType: "cp"}
type TraceInst struct {
TraceTime string
TraceType string
TraceStr string
}
// NameType is a an entry in a dictionary created for a trace
// that maps object id numbers to a (name,type) pair
type NameType struct {
Name string
Type string
}
// TraceManager implements the pces TraceManager interface. It is
// use to gather information about a simulation model and an execution of that model
type TraceManager struct {
// experiment uses trace
InUse bool `json:"inuse" yaml:"inuse"`
// name of experiment
ExpName string `json:"expname" yaml:"expname"`
// text name associated with each objID
NameByID map[int]NameType `json:"namebyid" yaml:"namebyid"`
// all trace records for this experiment
Traces map[int][]TraceInst `json:"traces" yaml:"traces"`
}
// CreateTraceManager is a constructor. It saves the name of the experiment
// and a flag indicating whether the trace manager is active. By testing this
// flag we can inhibit the activity of gathering a trace when we don't want it,
// while embedding calls to its methods everywhere we need them when it is
func CreateTraceManager(ExpName string, active bool) *TraceManager {
tm := new(TraceManager)
tm.InUse = active
tm.ExpName = ExpName
tm.NameByID = make(map[int]NameType) // dictionary of id code -> (name,type)
tm.Traces = make(map[int][]TraceInst) // traces have 'execution' origins, are saved by index to these
return tm
}
// Active tells the caller whether the Trace Manager is actively being used
func (tm *TraceManager) Active() bool {
return tm.InUse
}
// AddTrace creates a record of the trace using its calling arguments, and stores it
func (tm *TraceManager) AddTrace(vrt vrtime.Time, execID int, trace TraceInst) {
// return if we aren't using the trace manager
if !tm.InUse {
return
}
_, present := tm.Traces[execID]
if !present {
tm.Traces[execID] = make([]TraceInst, 0)
}
tm.Traces[execID] = append(tm.Traces[execID], trace)
}
// AddName is used to add an element to the id -> (name,type) dictionary for the trace file
func (tm *TraceManager) AddName(id int, name string, objDesc string) {
if tm.InUse {
_, present := tm.NameByID[id]
if present {
panic("duplicated id in AddName")
}
tm.NameByID[id] = NameType{Name: name, Type: objDesc}
}
}
// WriteToFile stores the Traces struct to the file whose name is given.
// Serialization to json or to yaml is selected based on the extension of this name.
func (tm *TraceManager) WriteToFile(filename string, globalOrder bool) bool {
if !tm.InUse {
return false
}
pathExt := path.Ext(filename)
var bytes []byte
var merr error = nil
if !globalOrder {
if pathExt == ".yaml" || pathExt == ".YAML" || pathExt == ".yml" {
bytes, merr = yaml.Marshal(*tm)
} else if pathExt == ".json" || pathExt == ".JSON" {
bytes, merr = json.MarshalIndent(*tm, "", "\t")
}
if merr != nil {
panic(merr)
}
} else {
ntm := new(TraceManager)
ntm.InUse = tm.InUse
ntm.ExpName = tm.ExpName
ntm.NameByID = make(map[int]NameType)
for key, value := range tm.NameByID {
ntm.NameByID[key] = value
}
ntm.Traces = make(map[int][]TraceInst)
ntm.Traces[0] = make([]TraceInst,0)
for _, valueList := range tm.Traces {
ntm.Traces[0] = append(ntm.Traces[0], valueList...)
}
sort.Slice(ntm.Traces[0], func(i,j int) bool {
v1, _ := strconv.ParseFloat(ntm.Traces[0][i].TraceTime, 64); v2, _ := strconv.ParseFloat(ntm.Traces[0][j].TraceTime, 64); return v1 < v2})
if pathExt == ".yaml" || pathExt == ".YAML" || pathExt == ".yml" {
bytes, merr = yaml.Marshal(*ntm)
} else if pathExt == ".json" || pathExt == ".JSON" {
bytes, merr = json.MarshalIndent(*ntm, "", "\t")
}
if merr != nil {
panic(merr)
}
}
f, cerr := os.Create(filename)
if cerr != nil {
panic(cerr)
}
_, werr := f.WriteString(string(bytes[:]))
if werr != nil {
panic(werr)
}
f.Close()
return true
}
// NetTrace saves information about the visitation of a message to some point in the simulation.
// saved for post-run analysis
type NetTrace struct {
Time float64 // time in float64
Ticks int64 // ticks variable of time
Priority int64 // priority field of time-stamp
FlowID int // integer identifier identifying the chain of traces this is part of
ExecID int
ConnectID int // integer identifier of the network connection
ObjID int // integer id for object being referenced
Op string // "start", "stop", "enter", "exit"
PcktIdx int // packet index inside of a multi-packet message
Packet bool // true if the event marks the passage of a packet (rather than flow)
MsgType string
Rate float64 // rate associated with the connection
}
func (ntr *NetTrace) TraceType() TraceRecordType {
return NetworkType
}
func (ntr *NetTrace) Serialize() string {
var bytes []byte
var merr error
bytes, merr = yaml.Marshal(*ntr)
if merr != nil {
panic(merr)
}
return string(bytes[:])
}
type SchedulerTrace struct {
Time float64
ObjID int
ExecID int
Op string
Cores int
Inservice int
Inbckgrnd int
Waiting int
}
func (st *SchedulerTrace) Serialize() string {
var bytes []byte
var merr error
bytes, merr = yaml.Marshal(*st)
if merr != nil {
panic(merr)
}
return string(bytes[:])
}
type IntrfcTrace struct {
Time float64
ObjID int
ExecID int
Op string
CQ string
}
func (it *IntrfcTrace) Serialize() string {
var bytes []byte
var merr error
bytes, merr = yaml.Marshal(*it)
if merr != nil {
panic(merr)
}
return string(bytes[:])
}
func AddIntrfcTrace(tm *TraceManager, vrt vrtime.Time, execID, objID int, op, CQ string) {
it := new(IntrfcTrace)
it.Time = vrt.Seconds()
it.ExecID = execID
it.ObjID = objID
it.Op = op
it.CQ = CQ
itStr := it.Serialize()
strTime := strconv.FormatFloat(it.Time, 'f', -1, 64)
trcInst := TraceInst{TraceTime: strTime, TraceType: "interface", TraceStr: itStr}
tm.AddTrace(vrt, execID, trcInst)
}
func AddSchedulerTrace(tm *TraceManager, vrt vrtime.Time, ts *TaskScheduler, execID, objID int, op string) {
endpt := EndptDevByID[objID]
if !endpt.EndptState.Trace {
return
}
st := new(SchedulerTrace)
st.Time = vrt.Seconds()
st.ExecID = execID
st.ObjID = objID
st.Op = op
st.Cores = ts.cores
st.Inservice = ts.inservice
st.Waiting = ts.numWaiting
st.Inbckgrnd = ts.inBckgrnd
stStr := st.Serialize()
traceTime := strconv.FormatFloat(vrt.Seconds(), 'f', -1, 64)
trcInst := TraceInst{TraceTime: traceTime, TraceType: "scheduler", TraceStr: stStr}
tm.AddTrace(vrt, st.ExecID, trcInst)
}
// AddNetTrace creates a record of the trace using its calling arguments, and stores it
func AddNetTrace(tm *TraceManager, vrt vrtime.Time, nm *NetworkMsg, objID int, op string) {
ntr := new(NetTrace)
ntr.Time = vrt.Seconds()
ntr.Ticks = vrt.Ticks()
ntr.Priority = vrt.Pri()
ntr.ConnectID = nm.ConnectID
ntr.FlowID = nm.FlowID
ntr.ObjID = objID
ntr.ExecID = nm.ExecID
ntr.Op = op
ntr.PcktIdx = nm.PcktIdx
ntr.MsgType = nmtToStr[nm.NetMsgType]
ntrStr := ntr.Serialize()
traceTime := strconv.FormatFloat(vrt.Seconds(), 'f', -1, 64)
trcInst := TraceInst{TraceTime: traceTime, TraceType: "network", TraceStr: ntrStr}
tm.AddTrace(vrt, ntr.ExecID, trcInst)
}