Commit f3e8a1fd authored by Kirill Smelkov's avatar Kirill Smelkov

.

parent f3f9949f
...@@ -30,6 +30,7 @@ import ( ...@@ -30,6 +30,7 @@ import (
"sync/atomic" "sync/atomic"
"lab.nexedi.com/kirr/neo/go/xcommon/xnet" "lab.nexedi.com/kirr/neo/go/xcommon/xnet"
_ "lab.nexedi.com/kirr/neo/go/xcommon/xnet/pipenet" // XXX temp
) )
// NodeLink is a node-node link in NEO // NodeLink is a node-node link in NEO
......
...@@ -59,10 +59,17 @@ type traceEvent struct { ...@@ -59,10 +59,17 @@ type traceEvent struct {
//Name string //Name string
//Argv string //Argv string
PkgPath string // XXX -> pkg ? // TODO += Pos
Pkgi *loader.PackageInfo
*ast.FuncDecl *ast.FuncDecl
} }
// traceImport represents 1 trace:import directive
type traceImport struct {
Pos token.Position
PkgPath string
}
// TypedArgv returns argument list with types // TypedArgv returns argument list with types
func (te *traceEvent) TypedArgv() string { func (te *traceEvent) TypedArgv() string {
//format.Node(&buf, fset, te.FuncDecl.Type.Params) //format.Node(&buf, fset, te.FuncDecl.Type.Params)
...@@ -96,12 +103,18 @@ func (te *traceEvent) Argv() string { ...@@ -96,12 +103,18 @@ func (te *traceEvent) Argv() string {
return strings.Join(argv, ", ") return strings.Join(argv, ", ")
} }
// byEventName provides []traceEvent ordering by event name // byEventName provides []*traceEvent ordering by event name
type byEventName []*traceEvent type byEventName []*traceEvent
func (v byEventName) Less(i, j int) bool { return v[i].Name.Name < v[j].Name.Name } func (v byEventName) Less(i, j int) bool { return v[i].Name.Name < v[j].Name.Name }
func (v byEventName) Swap(i, j int) { v[i], v[j] = v[j], v[i] } func (v byEventName) Swap(i, j int) { v[i], v[j] = v[j], v[i] }
func (v byEventName) Len() int { return len(v) } func (v byEventName) Len() int { return len(v) }
// byPkgPath provides []*traceImport ordering by package path
type byPkgPath []*traceImport
func (v byPkgPath) Less(i, j int) bool { return v[i].PkgPath < v[j].PkgPath }
func (v byPkgPath) Swap(i, j int) { v[i], v[j] = v[j], v[i] }
func (v byPkgPath) Len() int { return len(v) }
// traceEventCodeTmpl is code template generated for one trace event // traceEventCodeTmpl is code template generated for one trace event
var traceEventCodeTmpl = template.Must(template.New("traceevent").Parse(` var traceEventCodeTmpl = template.Must(template.New("traceevent").Parse(`
// traceevent: {{.Name}}({{.TypedArgv}}) XXX better raw .Text (e.g. comments) // traceevent: {{.Name}}({{.TypedArgv}}) XXX better raw .Text (e.g. comments)
...@@ -142,12 +155,10 @@ func {{.Name}}_Attach(pg *tracing.ProbeGroup, probe func({{.TypedArgv}})) *traci ...@@ -142,12 +155,10 @@ func {{.Name}}_Attach(pg *tracing.ProbeGroup, probe func({{.TypedArgv}})) *traci
`)) `))
// traceEventImportTmpl is code template generated for importing one trace event // traceEventImportTmpl is code template generated for importing one trace event
var traceEventImportTmpl = template.Must(template.New("traceimport").Parse(`
// traceimport: {{.Pkgi.Pkg.Path}} {{.Name}}
// FIXME func args typs must be qualified // FIXME func args typs must be qualified
var traceEventImportTmpl = template.Must(template.New("traceimport").Parse(`
//go:linkname {{.Pkgi.Pkg.Name}}_{{.Name}}_Attach {{.Pkgi.Pkg.Path}}.{{.Name}}_Attach //go:linkname {{.Pkgi.Pkg.Name}}_{{.Name}}_Attach {{.Pkgi.Pkg.Path}}.{{.Name}}_Attach
func {{.Pkgi.Pkg.Name}}_{{.Name}}_Attach(*tracing.ProbeGroup, func(.TypedArgv)) *tracing.Probe func {{.Pkgi.Pkg.Name}}_{{.Name}}_Attach(*tracing.ProbeGroup, func({{.TypedArgv}})) *tracing.Probe
`)) `))
// parseTraceEvent parses trace event definition into traceEvent // parseTraceEvent parses trace event definition into traceEvent
...@@ -179,20 +190,20 @@ func parseTraceEvent(pkgi *loader.PackageInfo, text string) (*traceEvent, error) ...@@ -179,20 +190,20 @@ func parseTraceEvent(pkgi *loader.PackageInfo, text string) (*traceEvent, error)
return nil, fmt.Errorf("trace event must not return results") return nil, fmt.Errorf("trace event must not return results")
} }
return &traceEvent{pkgi.Pkg.Path(), declf}, nil return &traceEvent{pkgi, declf}, nil
} }
// Package represents tracing-related information about a package // Package represents tracing-related information about a package
type Package struct { type Package struct {
PkgPath string PkgPath string
Eventv []*traceEvent // trace events this package defines Eventv []*traceEvent // trace events this package defines
Importv []string // packages (pkgpath) this package trace imports Importv []*traceImport // packages (pkgpath) this package trace imports
} }
// packageTrace returns tracing information about a package // packageTrace returns tracing information about a package
func packageTrace(lprog *loader.Program, pkgi *loader.PackageInfo) *Package { func packageTrace(lprog *loader.Program, pkgi *loader.PackageInfo) *Package {
eventv := []*traceEvent{} eventv := []*traceEvent{}
importv := []string{} importv := []*traceImport{}
// go through files of the package and process //trace: directives // go through files of the package and process //trace: directives
for _, file := range pkgi.Files { // ast.File for _, file := range pkgi.Files { // ast.File
...@@ -226,8 +237,13 @@ func packageTrace(lprog *loader.Program, pkgi *loader.PackageInfo) *Package { ...@@ -226,8 +237,13 @@ func packageTrace(lprog *loader.Program, pkgi *loader.PackageInfo) *Package {
eventv = append(eventv, event) eventv = append(eventv, event)
case "//trace:import": case "//trace:import":
// XXX reject duplicate imports // reject duplicate imports
importv = append(importv, arg) for _, imported := range importv {
if arg == imported.PkgPath {
log.Fatalf("%v: duplicate trace import of %v (previous at %v)", pos, arg, imported.Pos)
}
}
importv = append(importv, &traceImport{Pos: pos, PkgPath: arg})
default: default:
log.Fatalf("%v: unknown tracing directive %q", pos, directive) log.Fatalf("%v: unknown tracing directive %q", pos, directive)
...@@ -237,7 +253,7 @@ func packageTrace(lprog *loader.Program, pkgi *loader.PackageInfo) *Package { ...@@ -237,7 +253,7 @@ func packageTrace(lprog *loader.Program, pkgi *loader.PackageInfo) *Package {
} }
sort.Sort(byEventName(eventv)) sort.Sort(byEventName(eventv))
sort.Strings(importv) sort.Sort(byPkgPath(importv))
return &Package{PkgPath: pkgi.Pkg.Path(), Eventv: eventv, Importv: importv} return &Package{PkgPath: pkgi.Pkg.Path(), Eventv: eventv, Importv: importv}
} }
...@@ -268,7 +284,7 @@ func tracegen(pkgpath string) error { ...@@ -268,7 +284,7 @@ func tracegen(pkgpath string) error {
for _, event := range pkg.Eventv { for _, event := range pkg.Eventv {
err = traceEventCodeTmpl.Execute(os.Stdout, event) err = traceEventCodeTmpl.Execute(os.Stdout, event)
if err != nil { if err != nil {
panic(err) panic(err) // XXX
} }
} }
...@@ -276,8 +292,23 @@ func tracegen(pkgpath string) error { ...@@ -276,8 +292,23 @@ func tracegen(pkgpath string) error {
// generate code for trace:import imports // generate code for trace:import imports
fmt.Println() fmt.Println()
for _, pkgpath := range pkg.Importv { for _, timport := range pkg.Importv {
fmt.Printf("// traceimport TODO %v\n", pkgpath) fmt.Printf("// traceimport: %v\n", timport.PkgPath)
pkgi = lprog.Package(timport.PkgPath)
if pkgi == nil {
// TODO do not require vvv
log.Fatalf("%v: package %s must be also regularly imported", timport.Pos, timport.PkgPath)
}
pkg = packageTrace(lprog, pkgi)
for _, event := range pkg.Eventv {
err = traceEventImportTmpl.Execute(os.Stdout, event)
if err != nil {
panic(err) // XXX
}
}
} }
// TODO check export hash // TODO check export hash
......
...@@ -53,4 +53,19 @@ func traceConnSend_Attach(pg *tracing.ProbeGroup, probe func(c *Conn, msg Msg)) ...@@ -53,4 +53,19 @@ func traceConnSend_Attach(pg *tracing.ProbeGroup, probe func(c *Conn, msg Msg))
return &p.Probe return &p.Probe
} }
// traceimport TODO lab.nexedi.com/kirr/neo/go/xcommon/xnet/pipenet // traceimport: lab.nexedi.com/kirr/neo/go/xcommon/xnet/pipenet
//go:linkname pipenet_traceAccept_Attach lab.nexedi.com/kirr/neo/go/xcommon/xnet/pipenet.traceAccept_Attach
func pipenet_traceAccept_Attach(*tracing.ProbeGroup, func(conn net.Conn)) *tracing.Probe
//go:linkname pipenet_traceDial_Attach lab.nexedi.com/kirr/neo/go/xcommon/xnet/pipenet.traceDial_Attach
func pipenet_traceDial_Attach(*tracing.ProbeGroup, func(addr string)) *tracing.Probe
//go:linkname pipenet_traceListen_Attach lab.nexedi.com/kirr/neo/go/xcommon/xnet/pipenet.traceListen_Attach
func pipenet_traceListen_Attach(*tracing.ProbeGroup, func(laddr string)) *tracing.Probe
//go:linkname pipenet_traceNew_Attach lab.nexedi.com/kirr/neo/go/xcommon/xnet/pipenet.traceNew_Attach
func pipenet_traceNew_Attach(*tracing.ProbeGroup, func(name string)) *tracing.Probe
//go:linkname pipenet_traceNewHost_Attach lab.nexedi.com/kirr/neo/go/xcommon/xnet/pipenet.traceNewHost_Attach
func pipenet_traceNewHost_Attach(*tracing.ProbeGroup, func(host *Host)) *tracing.Probe
...@@ -137,6 +137,9 @@ func New(name string) *Network { ...@@ -137,6 +137,9 @@ func New(name string) *Network {
return &Network{name: name, hostMap: make(map[string]*Host)} return &Network{name: name, hostMap: make(map[string]*Host)}
} }
//XXX temp
//trace:event traceNewHost(host *Host)
// Host returns network access point by name // Host returns network access point by name
// if there was no such host before it creates new one // if there was no such host before it creates new one
func (n *Network) Host(name string) *Host { func (n *Network) Host(name string) *Host {
...@@ -147,6 +150,7 @@ func (n *Network) Host(name string) *Host { ...@@ -147,6 +150,7 @@ func (n *Network) Host(name string) *Host {
if host == nil { if host == nil {
host = &Host{network: n, name: name} host = &Host{network: n, name: name}
n.hostMap[name] = host n.hostMap[name] = host
traceNewHost(host)
} }
return host return host
...@@ -173,11 +177,15 @@ func (h *Host) resolveAddr(addr string) (host *Host, port int, err error) { ...@@ -173,11 +177,15 @@ func (h *Host) resolveAddr(addr string) (host *Host, port int, err error) {
return host, port, nil return host, port, nil
} }
// XXX temp
//trace:event traceListen(laddr string)
// Listen starts new listener // Listen starts new listener
// It either allocates free port if laddr is "", or binds to laddr. // It either allocates free port if laddr is "", or binds to laddr.
// Once listener is started, Dials could connect to listening address. // Once listener is started, Dials could connect to listening address.
// Connection requests created by Dials could be accepted via Accept. // Connection requests created by Dials could be accepted via Accept.
func (h *Host) Listen(laddr string) (net.Listener, error) { func (h *Host) Listen(laddr string) (net.Listener, error) {
traceListen(laddr)
h.network.mu.Lock() h.network.mu.Lock()
defer h.network.mu.Unlock() defer h.network.mu.Unlock()
...@@ -250,6 +258,9 @@ func (l *listener) Close() error { ...@@ -250,6 +258,9 @@ func (l *listener) Close() error {
return nil return nil
} }
// XXX temp
//trace:event traceAccept(conn net.Conn)
// Accept tries to connect to Dial called with addr corresponding to our listener // Accept tries to connect to Dial called with addr corresponding to our listener
func (l *listener) Accept() (net.Conn, error) { func (l *listener) Accept() (net.Conn, error) {
h := l.socket.host h := l.socket.host
...@@ -274,13 +285,18 @@ func (l *listener) Accept() (net.Conn, error) { ...@@ -274,13 +285,18 @@ func (l *listener) Accept() (net.Conn, error) {
n.mu.Unlock() n.mu.Unlock()
req.resp <- skc.conn req.resp <- skc.conn
traceAccept(sks.conn)
return sks.conn, nil return sks.conn, nil
} }
} }
// XXX temp
//trace:event traceDial(addr string)
// Dial dials address on the network // Dial dials address on the network
// It tries to connect to Accept called on listener corresponding to addr. // It tries to connect to Accept called on listener corresponding to addr.
func (h *Host) Dial(ctx context.Context, addr string) (net.Conn, error) { func (h *Host) Dial(ctx context.Context, addr string) (net.Conn, error) {
traceDial(addr)
var netaddr net.Addr var netaddr net.Addr
derr := func(err error) error { derr := func(err error) error {
return &net.OpError{Op: "dial", Net: h.Network(), Addr: netaddr, Err: err} return &net.OpError{Op: "dial", Net: h.Network(), Addr: netaddr, Err: err}
......
Markdown is supported
0%
or
You are about to add 0 people to the discussion. Proceed with caution.
Finish editing this message first!
Please register or to comment