master
go 112 lines 2.55 KB
Raw
1 // SPDX-License-Identifier: GPL-3.0-or-later
2
3 package snmp
4
5 import (
6 "context"
7 "fmt"
8 "sync"
9
10 "github.com/netdata/netdata/go/plugins/pkg/funcapi"
11 "github.com/netdata/netdata/go/plugins/plugin/framework/collectorapi"
12 )
13
14 // funcRouter routes method calls to appropriate function handlers.
15 type funcRouter struct {
16 ifaceCache *ifaceCache
17
18 mu sync.RWMutex
19 handlers map[string]funcapi.MethodHandler
20 }
21
22 type registeredSNMPFunction struct {
23 methodID string
24 handler funcapi.MethodHandler
25 }
26
27 func newFuncRouter(ifaceCache *ifaceCache, extraHandlers ...registeredSNMPFunction) *funcRouter {
28 r := &funcRouter{
29 ifaceCache: ifaceCache,
30 handlers: make(map[string]funcapi.MethodHandler),
31 }
32 r.registerHandler(ifacesMethodID, newFuncInterfaces(r))
33 for _, h := range collectorSpecificFunctionHandlers() {
34 if h.methodID != "" {
35 r.registerHandler(h.methodID, h.handler)
36 }
37 }
38 for _, h := range extraHandlers {
39 if h.methodID != "" {
40 r.registerHandler(h.methodID, h.handler)
41 }
42 }
43 addTopologyFunctionHandler(r.handlers)
44 return r
45 }
46
47 func (r *funcRouter) registerHandler(method string, handler funcapi.MethodHandler) {
48 if r == nil || handler == nil {
49 return
50 }
51 r.mu.Lock()
52 defer r.mu.Unlock()
53
54 if r.handlers == nil {
55 r.handlers = make(map[string]funcapi.MethodHandler)
56 }
57 r.handlers[method] = handler
58 }
59
60 // Compile-time interface check.
61 var _ funcapi.MethodHandler = (*funcRouter)(nil)
62
63 func (r *funcRouter) MethodParams(ctx context.Context, method string) ([]funcapi.ParamConfig, error) {
64 r.mu.RLock()
65 h, ok := r.handlers[method]
66 r.mu.RUnlock()
67
68 if ok {
69 return h.MethodParams(ctx, method)
70 }
71 return nil, fmt.Errorf("unknown method: %s", method)
72 }
73
74 func (r *funcRouter) Handle(ctx context.Context, method string, params funcapi.ResolvedParams) *funcapi.FunctionResponse {
75 r.mu.RLock()
76 h, ok := r.handlers[method]
77 r.mu.RUnlock()
78
79 if ok {
80 return h.Handle(ctx, method, params)
81 }
82 return funcapi.NotFoundResponse(method)
83 }
84
85 func (r *funcRouter) Cleanup(ctx context.Context) {
86 r.mu.RLock()
87 handlers := make([]funcapi.MethodHandler, 0, len(r.handlers))
88 for _, h := range r.handlers {
89 handlers = append(handlers, h)
90 }
91 r.mu.RUnlock()
92
93 for _, h := range handlers {
94 h.Cleanup(ctx)
95 }
96 }
97
98 func snmpBaseMethods() []funcapi.MethodConfig {
99 methods := []funcapi.MethodConfig{
100 ifacesMethodConfig(),
101 }
102 methods = append(methods, collectorSpecificMethodConfigs()...)
103 return appendTopologyMethodConfig(methods)
104 }
105
106 func snmpFunctionHandler(job collectorapi.RuntimeJob) funcapi.MethodHandler {
107 c, ok := job.Collector().(*Collector)
108 if !ok {
109 return nil
110 }
111 return c.funcRouter
112 }