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 1
func New(logger *zap.SugaredLogger, ports config.Ports, nodes ...*ipfs.NodeInfo) *NodeRegistry {
39
	// parse nodes
40 1
	m := make(map[string]*ipfs.NodeInfo)
41 1
	if nodes != nil {
42 1
		for _, n := range nodes {
43 1
			m[n.NetworkID] = n
44
		}
45
	}
46

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

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

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

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

69 1
	if _, found := r.nodes[node.NetworkID]; found {
70 1
		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 1
	if node.Ports.Swarm == "" || node.Ports.Gateway == "" || node.Ports.API == "" {
76 1
		var err error
77 1
		var swarm, api, gateway string
78 1
		if swarm, err = r.swarmPorts.AssignPort(); err != nil {
79 1
			return fmt.Errorf("failed to register node: %s", err.Error())
80
		}
81 1
		if api, err = r.apiPorts.AssignPort(); err != nil {
82 1
			return fmt.Errorf("failed to register node: %s", err.Error())
83
		}
84 1
		if gateway, err = r.gatewayPorts.AssignPort(); err != nil {
85 1
			return fmt.Errorf("failed to register node: %s", err.Error())
86
		}
87 1
		node.Ports = ipfs.NodePorts{Swarm: swarm, API: api, Gateway: gateway}
88
	}
89

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

92 1
	return nil
93
}
94

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

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

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

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

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

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

126 1
	return nodes
127
}
128

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

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

145 1
	return node, nil
146
}
147

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

Read our documentation on viewing source code .

Loading