1
package registry
2

3
import (
4
	"errors"
5
	"fmt"
6
	"sync"
7

8
	"go.uber.org/zap"
9

10
	"github.com/RTradeLtd/Nexus/config"
11
	"github.com/RTradeLtd/Nexus/ipfs"
12
	"github.com/RTradeLtd/Nexus/network"
13
)
14

15
const (
16
	// ErrInvalidNetwork is returned when an invalid node ID is provided
17
	ErrInvalidNetwork = "invalid node network"
18

19
	// ErrNetworkExists is returned when an network is provided that already exists
20
	ErrNetworkExists = "network already exists"
21
)
22

23
// NodeRegistry manages data on active nodes
24
type NodeRegistry struct {
25
	l *zap.SugaredLogger
26

27
	// node registry - locked by NodeRegistry::nm
28
	nodes map[string]*ipfs.NodeInfo
29
	nm    sync.RWMutex
30

31
	// port registry
32
	swarmPorts   *network.Registry
33
	apiPorts     *network.Registry
34
	gatewayPorts *network.Registry
35
}
36

37
// New sets up a new registry with provided nodes
38 2
func New(logger *zap.SugaredLogger, ports config.Ports, nodes ...*ipfs.NodeInfo) *NodeRegistry {
39
	// parse nodes
40 2
	m := make(map[string]*ipfs.NodeInfo)
41 2
	if nodes != nil {
42 2
		for _, n := range nodes {
43 2
			m[n.NetworkID] = n
44
		}
45
	}
46

47
	// build registry
48 2
	return &NodeRegistry{
49 2
		l:     logger.Named("registry"),
50 2
		nodes: m,
51

52
		// See documentation regarding public/private-ness of IPFS ports in package
53
		// ipfs
54 2
		swarmPorts:   network.NewRegistry(logger, network.Public, ports.Swarm),
55 2
		apiPorts:     network.NewRegistry(logger, network.Private, ports.API),
56 2
		gatewayPorts: network.NewRegistry(logger, network.Private, ports.Gateway),
57
	}
58
}
59

60
// Register registers a node and allocates appropriate ports
61 2
func (r *NodeRegistry) Register(node *ipfs.NodeInfo) error {
62 2
	if node.NetworkID == "" {
63 2
		return errors.New(ErrInvalidNetwork)
64
	}
65

66 2
	r.nm.Lock()
67 2
	defer r.nm.Unlock()
68

69 2
	if _, found := r.nodes[node.NetworkID]; found {
70 2
		return errors.New(ErrNetworkExists)
71
	}
72

73
	// assign ports to this node - do not assign new ones if ports are already
74
	// provided in node.Ports
75 2
	if node.Ports.Swarm == "" || node.Ports.Gateway == "" || node.Ports.API == "" {
76 2
		var err error
77 2
		var swarm, api, gateway string
78 2
		if swarm, err = r.swarmPorts.AssignPort(); err != nil {
79 2
			return fmt.Errorf("failed to register node: %s", err.Error())
80
		}
81 2
		if api, err = r.apiPorts.AssignPort(); err != nil {
82 2
			return fmt.Errorf("failed to register node: %s", err.Error())
83
		}
84 2
		if gateway, err = r.gatewayPorts.AssignPort(); err != nil {
85 2
			return fmt.Errorf("failed to register node: %s", err.Error())
86
		}
87 2
		node.Ports = ipfs.NodePorts{Swarm: swarm, API: api, Gateway: gateway}
88
	}
89

90 2
	r.nodes[node.NetworkID] = node
91

92 2
	return nil
93
}
94

95
// Deregister removes node with given network
96 2
func (r *NodeRegistry) Deregister(network string) error {
97 2
	if network == "" {
98 2
		return errors.New(ErrInvalidNetwork)
99
	}
100

101 2
	r.nm.Lock()
102 2
	defer r.nm.Unlock()
103

104 2
	if _, found := r.nodes[network]; !found {
105 2
		return fmt.Errorf("node for network '%s' not found", network)
106
	}
107

108 2
	delete(r.nodes, network)
109 2
	return nil
110
}
111

112
// List retrieves a list of all known nodes
113 2
func (r *NodeRegistry) List() []ipfs.NodeInfo {
114 2
	var (
115 2
		nodes = make([]ipfs.NodeInfo, len(r.nodes))
116 2
		i     = 0
117 2
	)
118

119 2
	r.nm.RLock()
120 2
	for _, n := range r.nodes {
121 2
		nodes[i] = *n
122 2
		i++
123
	}
124 2
	r.nm.RUnlock()
125

126 2
	return nodes
127
}
128

129
// Get retrieves details about node with given network
130 2
func (r *NodeRegistry) Get(network string) (ipfs.NodeInfo, error) {
131 2
	var node ipfs.NodeInfo
132 2
	if network == "" {
133 2
		return node, errors.New(ErrInvalidNetwork)
134
	}
135

136 2
	r.nm.RLock()
137 2
	n, found := r.nodes[network]
138 2
	if !found {
139 2
		r.nm.RUnlock()
140 2
		return node, fmt.Errorf("node for network '%s' not found", network)
141
	}
142 2
	node = *n
143 2
	r.nm.RUnlock()
144

145 2
	return node, nil
146
}
147

148
// Close stops registry background jobs
149 2
func (r *NodeRegistry) Close() {
150 2
	r.apiPorts.Close()
151 2
	r.gatewayPorts.Close()
152 2
	r.swarmPorts.Close()
153
}

Read our documentation on viewing source code .

Loading