2019-01-24 20:15:10 +00:00
// Copyright (C) 2019 Storj Labs, Inc.
2018-04-18 17:55:28 +01:00
// See LICENSE for copying information.
2018-06-13 19:22:32 +01:00
package overlay
2018-04-18 16:34:15 +01:00
import (
2018-05-16 19:47:59 +01:00
"context"
2019-01-15 16:08:45 +00:00
"errors"
2019-05-30 18:35:04 +01:00
"net"
2019-04-04 17:34:36 +01:00
"time"
2018-04-18 16:34:15 +01:00
2018-06-13 19:22:32 +01:00
"github.com/zeebo/errs"
2018-12-22 04:51:42 +00:00
"go.uber.org/zap"
2018-11-16 16:31:14 +00:00
2018-09-18 05:39:06 +01:00
"storj.io/storj/pkg/pb"
2018-11-30 13:40:13 +00:00
"storj.io/storj/pkg/storj"
2018-06-13 19:22:32 +01:00
"storj.io/storj/storage"
2018-04-18 16:34:15 +01:00
)
2018-12-17 18:47:26 +00:00
// ErrEmptyNode is returned when the nodeID is empty
var ErrEmptyNode = errs . New ( "empty node ID" )
// ErrNodeNotFound is returned if a node does not exist in database
2019-03-29 08:53:43 +00:00
var ErrNodeNotFound = errs . Class ( "node not found" )
2018-11-21 17:31:27 +00:00
2019-05-27 12:13:47 +01:00
// ErrNodeOffline is returned if a nodes is offline
var ErrNodeOffline = errs . Class ( "node is offline" )
2019-06-24 15:46:10 +01:00
// ErrNodeDisqualified is returned if a nodes is disqualified
var ErrNodeDisqualified = errs . Class ( "node is disqualified" )
2019-01-31 18:49:00 +00:00
// ErrNotEnoughNodes is when selecting nodes failed with the given parameters
var ErrNotEnoughNodes = errs . Class ( "not enough nodes" )
2019-08-06 17:35:59 +01:00
// DB implements the database for overlay.Service
2019-09-10 14:24:16 +01:00
//
// architecture: Database
2019-01-15 16:08:45 +00:00
type DB interface {
2019-02-11 19:24:51 +00:00
// SelectStorageNodes looks up nodes based on criteria
SelectStorageNodes ( ctx context . Context , count int , criteria * NodeCriteria ) ( [ ] * pb . Node , error )
// SelectNewStorageNodes looks up nodes based on new node criteria
2019-04-23 21:47:11 +01:00
SelectNewStorageNodes ( ctx context . Context , count int , criteria * NodeCriteria ) ( [ ] * pb . Node , error )
2019-01-31 18:49:00 +00:00
2019-01-15 16:08:45 +00:00
// Get looks up the node by nodeID
2019-04-04 17:34:36 +01:00
Get ( ctx context . Context , nodeID storj . NodeID ) ( * NodeDossier , error )
2019-06-18 23:22:14 +01:00
// KnownOffline filters a set of nodes to offline nodes
KnownOffline ( context . Context , * NodeCriteria , storj . NodeIDList ) ( storj . NodeIDList , error )
2019-05-01 14:45:52 +01:00
// KnownUnreliableOrOffline filters a set of nodes to unhealth or offlines node, independent of new
KnownUnreliableOrOffline ( context . Context , * NodeCriteria , storj . NodeIDList ) ( storj . NodeIDList , error )
2019-07-08 23:04:35 +01:00
// Reliable returns all nodes that are reliable
Reliable ( context . Context , * NodeCriteria ) ( storj . NodeIDList , error )
2019-01-30 16:29:18 +00:00
// Paginate will page through the database nodes
2019-04-04 17:34:36 +01:00
Paginate ( ctx context . Context , offset int64 , limit int ) ( [ ] * NodeDossier , bool , error )
2019-07-12 15:35:48 +01:00
// PaginateQualified will page through the qualified nodes
PaginateQualified ( ctx context . Context , offset int64 , limit int ) ( [ ] * pb . Node , bool , error )
2019-04-22 10:07:50 +01:00
// Update updates node address
2019-06-20 14:56:04 +01:00
UpdateAddress ( ctx context . Context , value * pb . Node , defaults NodeSelectionConfig ) error
2019-07-31 18:21:06 +01:00
// BatchUpdateStats updates multiple storagenode's stats in one transaction
BatchUpdateStats ( ctx context . Context , updateRequests [ ] * UpdateRequest , batchSize int ) ( failed storj . NodeIDList , err error )
2019-03-25 22:25:09 +00:00
// UpdateStats all parts of single storagenode's stats.
UpdateStats ( ctx context . Context , request * UpdateRequest ) ( stats * NodeStats , err error )
2019-04-10 07:04:24 +01:00
// UpdateNodeInfo updates node dossier with info requested from the node itself like node type, email, wallet, capacity, and version.
UpdateNodeInfo ( ctx context . Context , node storj . NodeID , nodeInfo * pb . InfoResponse ) ( stats * NodeDossier , err error )
2019-03-25 22:25:09 +00:00
// UpdateUptime updates a single storagenode's uptime stats.
2019-06-20 14:56:04 +01:00
UpdateUptime ( ctx context . Context , nodeID storj . NodeID , isUp bool , lambda , weight , uptimeDQ float64 ) ( stats * NodeStats , err error )
2019-09-19 19:37:31 +01:00
// UpdateCheckIn updates a single storagenode's check-in stats.
UpdateCheckIn ( ctx context . Context , node NodeCheckInInfo , config NodeSelectionConfig ) ( err error )
2019-08-27 13:37:42 +01:00
// AllPieceCounts returns a map of node IDs to piece counts from the db.
AllPieceCounts ( ctx context . Context ) ( pieceCounts map [ storj . NodeID ] int , err error )
// UpdatePieceCounts sets the piece count field for the given node IDs.
UpdatePieceCounts ( ctx context . Context , pieceCounts map [ storj . NodeID ] int ) ( err error )
2019-10-01 23:18:21 +01:00
// UpdateExitStatus is used to update a node's graceful exit status.
UpdateExitStatus ( ctx context . Context , request * ExitStatusRequest ) ( stats * NodeStats , err error )
// GetExitingNodes returns nodes who have initiated a graceful exit, but have not completed it.
2019-10-24 17:24:42 +01:00
GetExitingNodes ( ctx context . Context ) ( exitingNodes [ ] * ExitStatus , err error )
2019-10-23 02:06:01 +01:00
// GetGracefulExitCompletedByTimeFrame returns nodes who have completed graceful exit within a time window (time window is around graceful exit completion).
GetGracefulExitCompletedByTimeFrame ( ctx context . Context , begin , end time . Time ) ( exitedNodes storj . NodeIDList , err error )
// GetGracefulExitIncompleteByTimeFrame returns nodes who have initiated, but not completed graceful exit within a time window (time window is around graceful exit initiation).
GetGracefulExitIncompleteByTimeFrame ( ctx context . Context , begin , end time . Time ) ( exitingNodes storj . NodeIDList , err error )
// GetExitStatus returns a node's graceful exit status.
2019-10-11 22:18:05 +01:00
GetExitStatus ( ctx context . Context , nodeID storj . NodeID ) ( exitStatus * ExitStatus , err error )
2019-01-15 16:08:45 +00:00
}
2019-09-19 19:37:31 +01:00
// NodeCheckInInfo contains all the info that will be updated when a node checkins
type NodeCheckInInfo struct {
NodeID storj . NodeID
Address * pb . NodeAddress
LastIP string
IsUp bool
Operator * pb . NodeOperator
Capacity * pb . NodeCapacity
Version * pb . NodeVersion
}
2019-03-23 08:06:11 +00:00
// FindStorageNodesRequest defines easy request parameters.
type FindStorageNodesRequest struct {
MinimumRequiredNodes int
RequestedCount int
2019-04-26 13:15:06 +01:00
FreeBandwidth int64
FreeDisk int64
ExcludedNodes [ ] storj . NodeID
MinimumVersion string // semver or empty
2019-03-23 08:06:11 +00:00
}
// NodeCriteria are the requirements for selecting nodes
type NodeCriteria struct {
2019-06-18 18:40:28 +01:00
FreeBandwidth int64
FreeDisk int64
AuditCount int64
UptimeCount int64
ExcludedNodes [ ] storj . NodeID
ExcludedIPs [ ] string
MinimumVersion string // semver or empty
OnlineWindow time . Duration
DistinctIP bool
2019-03-23 08:06:11 +00:00
}
2019-03-25 22:25:09 +00:00
// UpdateRequest is used to update a node status.
type UpdateRequest struct {
NodeID storj . NodeID
AuditSuccess bool
IsUp bool
2019-06-20 14:56:04 +01:00
// n.b. these are set values from the satellite.
// They are part of the UpdateRequest struct in order to be
// more easily accessible in satellite/satellitedb/overlaycache.go.
AuditLambda float64
AuditWeight float64
AuditDQ float64
UptimeLambda float64
UptimeWeight float64
UptimeDQ float64
2019-03-25 22:25:09 +00:00
}
2019-10-11 22:18:05 +01:00
// ExitStatus is used for reading graceful exit status.
type ExitStatus struct {
NodeID storj . NodeID
ExitInitiatedAt * time . Time
ExitLoopCompletedAt * time . Time
ExitFinishedAt * time . Time
2019-10-17 16:01:39 +01:00
ExitSuccess bool
2019-10-11 22:18:05 +01:00
}
2019-10-01 23:18:21 +01:00
// ExitStatusRequest is used to update a node's graceful exit status.
type ExitStatusRequest struct {
NodeID storj . NodeID
ExitInitiatedAt time . Time
ExitLoopCompletedAt time . Time
ExitFinishedAt time . Time
2019-10-17 16:01:39 +01:00
ExitSuccess bool
2019-10-01 23:18:21 +01:00
}
2019-04-04 17:34:36 +01:00
// NodeDossier is the complete info that the satellite tracks for a storage node
type NodeDossier struct {
pb . Node
2019-05-30 22:38:23 +01:00
Type pb . NodeType
Operator pb . NodeOperator
Capacity pb . NodeCapacity
Reputation NodeStats
Version pb . NodeVersion
Contained bool
2019-06-18 10:14:31 +01:00
Disqualified * time . Time
2019-08-19 11:58:13 +01:00
PieceCount int64
2019-10-11 22:18:05 +01:00
ExitStatus ExitStatus
2019-10-23 02:06:01 +01:00
CreatedAt time . Time
2019-04-04 17:34:36 +01:00
}
2019-03-29 08:53:43 +00:00
// NodeStats contains statistics about a node.
2019-03-25 22:25:09 +00:00
type NodeStats struct {
2019-06-17 21:48:04 +01:00
Latency90 int64
AuditSuccessCount int64
AuditCount int64
UptimeSuccessCount int64
UptimeCount int64
LastContactSuccess time . Time
LastContactFailure time . Time
AuditReputationAlpha float64
UptimeReputationAlpha float64
AuditReputationBeta float64
UptimeReputationBeta float64
2019-06-20 14:56:04 +01:00
Disqualified * time . Time
2019-03-25 22:25:09 +00:00
}
2019-08-06 17:35:59 +01:00
// Service is used to store and handle node information
2019-09-10 14:24:16 +01:00
//
// architecture: Service
2019-08-06 17:35:59 +01:00
type Service struct {
2019-07-31 18:21:06 +01:00
log * zap . Logger
db DB
config Config
2018-04-18 16:34:15 +01:00
}
2019-08-06 17:35:59 +01:00
// NewService returns a new Service
func NewService ( log * zap . Logger , db DB , config Config ) * Service {
return & Service {
2019-07-31 18:21:06 +01:00
log : log ,
db : db ,
config : config ,
2019-03-23 08:06:11 +00:00
}
2018-12-20 13:57:54 +00:00
}
2019-01-18 13:54:08 +00:00
// Close closes resources
2019-08-06 17:35:59 +01:00
func ( service * Service ) Close ( ) error { return nil }
2019-01-18 13:54:08 +00:00
2018-12-20 13:57:54 +00:00
// Inspect lists limited number of items in the cache
2019-08-06 17:35:59 +01:00
func ( service * Service ) Inspect ( ctx context . Context ) ( _ storage . Keys , err error ) {
2019-06-04 12:36:27 +01:00
defer mon . Task ( ) ( & ctx ) ( & err )
2019-01-15 16:08:45 +00:00
// TODO: implement inspection tools
return nil , errors . New ( "not implemented" )
2018-06-13 19:22:32 +01:00
}
2019-01-30 16:29:18 +00:00
// Paginate returns a list of `limit` nodes starting from `start` offset.
2019-08-06 17:35:59 +01:00
func ( service * Service ) Paginate ( ctx context . Context , offset int64 , limit int ) ( _ [ ] * NodeDossier , _ bool , err error ) {
2019-03-23 08:06:11 +00:00
defer mon . Task ( ) ( & ctx ) ( & err )
2019-08-06 17:35:59 +01:00
return service . db . Paginate ( ctx , offset , limit )
2019-01-30 16:29:18 +00:00
}
2019-07-12 15:35:48 +01:00
// PaginateQualified returns a list of `limit` qualified nodes starting from `start` offset.
2019-08-06 17:35:59 +01:00
func ( service * Service ) PaginateQualified ( ctx context . Context , offset int64 , limit int ) ( _ [ ] * pb . Node , _ bool , err error ) {
2019-07-12 15:35:48 +01:00
defer mon . Task ( ) ( & ctx ) ( & err )
2019-08-06 17:35:59 +01:00
return service . db . PaginateQualified ( ctx , offset , limit )
2019-07-12 15:35:48 +01:00
}
2019-08-06 17:35:59 +01:00
// Get looks up the provided nodeID from the overlay.
func ( service * Service ) Get ( ctx context . Context , nodeID storj . NodeID ) ( _ * NodeDossier , err error ) {
2019-03-23 08:06:11 +00:00
defer mon . Task ( ) ( & ctx ) ( & err )
2018-12-17 18:47:26 +00:00
if nodeID . IsZero ( ) {
return nil , ErrEmptyNode
}
2019-08-06 17:35:59 +01:00
return service . db . Get ( ctx , nodeID )
2018-04-18 16:34:15 +01:00
}
2019-04-23 23:45:50 +01:00
// IsOnline checks if a node is 'online' based on the collected statistics.
2019-08-06 17:35:59 +01:00
func ( service * Service ) IsOnline ( node * NodeDossier ) bool {
2019-08-22 12:40:15 +01:00
return time . Since ( node . Reputation . LastContactSuccess ) < service . config . Node . OnlineWindow ||
2019-04-23 23:45:50 +01:00
node . Reputation . LastContactSuccess . After ( node . Reputation . LastContactFailure )
}
2019-03-23 08:06:11 +00:00
// FindStorageNodes searches the overlay network for nodes that meet the provided requirements
2019-08-06 17:35:59 +01:00
func ( service * Service ) FindStorageNodes ( ctx context . Context , req FindStorageNodesRequest ) ( _ [ ] * pb . Node , err error ) {
2019-06-04 12:36:27 +01:00
defer mon . Task ( ) ( & ctx ) ( & err )
2019-08-06 17:35:59 +01:00
return service . FindStorageNodesWithPreferences ( ctx , req , & service . config . Node )
2019-03-23 08:06:11 +00:00
}
// FindStorageNodesWithPreferences searches the overlay network for nodes that meet the provided criteria
2019-08-06 17:35:59 +01:00
func ( service * Service ) FindStorageNodesWithPreferences ( ctx context . Context , req FindStorageNodesRequest , preferences * NodeSelectionConfig ) ( nodes [ ] * pb . Node , err error ) {
2019-03-23 08:06:11 +00:00
defer mon . Task ( ) ( & ctx ) ( & err )
2019-01-31 18:49:00 +00:00
// TODO: add sanity limits to requested node count
// TODO: add sanity limits to excluded nodes
2019-03-23 08:06:11 +00:00
reputableNodeCount := req . MinimumRequiredNodes
2019-01-31 18:49:00 +00:00
if reputableNodeCount <= 0 {
2019-03-23 08:06:11 +00:00
reputableNodeCount = req . RequestedCount
2019-01-31 18:49:00 +00:00
}
2019-05-22 21:06:27 +01:00
excludedNodes := req . ExcludedNodes
2019-04-23 16:23:51 +01:00
newNodeCount := 0
if preferences . NewNodePercentage > 0 {
newNodeCount = int ( float64 ( reputableNodeCount ) * preferences . NewNodePercentage )
}
var newNodes [ ] * pb . Node
if newNodeCount > 0 {
2019-08-06 17:35:59 +01:00
newNodes , err = service . db . SelectNewStorageNodes ( ctx , newNodeCount , & NodeCriteria {
2019-06-18 18:40:28 +01:00
FreeBandwidth : req . FreeBandwidth ,
FreeDisk : req . FreeDisk ,
AuditCount : preferences . AuditCount ,
ExcludedNodes : excludedNodes ,
MinimumVersion : preferences . MinimumVersion ,
OnlineWindow : preferences . OnlineWindow ,
DistinctIP : preferences . DistinctIP ,
2019-04-23 16:23:51 +01:00
} )
if err != nil {
2019-08-06 17:35:59 +01:00
return nil , Error . Wrap ( err )
2019-04-23 16:23:51 +01:00
}
}
2019-05-22 21:06:27 +01:00
var excludedIPs [ ] string
// add selected new nodes and their IPs to the excluded lists for reputable node selection
2019-04-23 16:23:51 +01:00
for _ , newNode := range newNodes {
2019-05-22 21:06:27 +01:00
excludedNodes = append ( excludedNodes , newNode . Id )
if preferences . DistinctIP {
excludedIPs = append ( excludedIPs , newNode . LastIp )
}
2019-04-23 16:23:51 +01:00
}
2019-05-07 15:44:47 +01:00
criteria := NodeCriteria {
2019-06-18 18:40:28 +01:00
FreeBandwidth : req . FreeBandwidth ,
FreeDisk : req . FreeDisk ,
AuditCount : preferences . AuditCount ,
UptimeCount : preferences . UptimeCount ,
ExcludedNodes : excludedNodes ,
ExcludedIPs : excludedIPs ,
MinimumVersion : preferences . MinimumVersion ,
OnlineWindow : preferences . OnlineWindow ,
DistinctIP : preferences . DistinctIP ,
2019-05-07 15:44:47 +01:00
}
2019-08-06 17:35:59 +01:00
reputableNodes , err := service . db . SelectStorageNodes ( ctx , reputableNodeCount - len ( newNodes ) , & criteria )
2019-01-31 18:49:00 +00:00
if err != nil {
2019-08-06 17:35:59 +01:00
return nil , Error . Wrap ( err )
2019-01-31 18:49:00 +00:00
}
nodes = append ( nodes , newNodes ... )
nodes = append ( nodes , reputableNodes ... )
2019-04-23 16:23:51 +01:00
if len ( nodes ) < reputableNodeCount {
2019-05-07 15:44:47 +01:00
return nodes , ErrNotEnoughNodes . New ( "requested %d found %d; %+v " , reputableNodeCount , len ( nodes ) , criteria )
2019-01-31 18:49:00 +00:00
}
return nodes , nil
}
2019-06-18 23:22:14 +01:00
// KnownOffline filters a set of nodes to offline nodes
2019-08-06 17:35:59 +01:00
func ( service * Service ) KnownOffline ( ctx context . Context , nodeIds storj . NodeIDList ) ( offlineNodes storj . NodeIDList , err error ) {
2019-06-18 23:22:14 +01:00
defer mon . Task ( ) ( & ctx ) ( & err )
criteria := & NodeCriteria {
2019-08-06 17:35:59 +01:00
OnlineWindow : service . config . Node . OnlineWindow ,
2019-06-18 23:22:14 +01:00
}
2019-08-06 17:35:59 +01:00
return service . db . KnownOffline ( ctx , criteria , nodeIds )
2019-06-18 23:22:14 +01:00
}
2019-05-10 20:05:42 +01:00
// KnownUnreliableOrOffline filters a set of nodes to unhealth or offlines node, independent of new.
2019-08-06 17:35:59 +01:00
func ( service * Service ) KnownUnreliableOrOffline ( ctx context . Context , nodeIds storj . NodeIDList ) ( badNodes storj . NodeIDList , err error ) {
2019-03-23 08:06:11 +00:00
defer mon . Task ( ) ( & ctx ) ( & err )
2019-05-01 14:45:52 +01:00
criteria := & NodeCriteria {
2019-08-06 17:35:59 +01:00
OnlineWindow : service . config . Node . OnlineWindow ,
2018-09-11 05:52:14 +01:00
}
2019-08-06 17:35:59 +01:00
return service . db . KnownUnreliableOrOffline ( ctx , criteria , nodeIds )
2018-09-11 05:52:14 +01:00
}
2019-07-08 23:04:35 +01:00
// Reliable filters a set of nodes that are reliable, independent of new.
2019-08-06 17:35:59 +01:00
func ( service * Service ) Reliable ( ctx context . Context ) ( nodes storj . NodeIDList , err error ) {
2019-07-08 23:04:35 +01:00
defer mon . Task ( ) ( & ctx ) ( & err )
criteria := & NodeCriteria {
2019-08-06 17:35:59 +01:00
OnlineWindow : service . config . Node . OnlineWindow ,
2019-07-08 23:04:35 +01:00
}
2019-08-06 17:35:59 +01:00
return service . db . Reliable ( ctx , criteria )
2019-07-08 23:04:35 +01:00
}
2019-08-06 17:35:59 +01:00
// Put adds a node id and proto definition into the overlay.
func ( service * Service ) Put ( ctx context . Context , nodeID storj . NodeID , value pb . Node ) ( err error ) {
2019-03-23 08:06:11 +00:00
defer mon . Task ( ) ( & ctx ) ( & err )
2019-10-04 21:48:41 +01:00
// If we get a Node without an ID
// we don't want to add to the database
2018-12-17 18:47:26 +00:00
if nodeID . IsZero ( ) {
2018-11-20 16:54:52 +00:00
return nil
}
2019-01-15 16:08:45 +00:00
if nodeID != value . Id {
return errors . New ( "invalid request" )
}
2019-05-30 18:35:04 +01:00
if value . Address == nil {
return errors . New ( "node has no address" )
}
2019-08-06 23:56:12 +01:00
2019-06-24 16:33:18 +01:00
// Resolve IP Address Network to ensure it is set
value . LastIp , err = GetNetwork ( ctx , value . Address . Address )
2019-05-30 18:35:04 +01:00
if err != nil {
2019-08-06 17:35:59 +01:00
return Error . Wrap ( err )
2019-05-30 18:35:04 +01:00
}
2019-08-06 17:35:59 +01:00
return service . db . UpdateAddress ( ctx , & value , service . config . Node )
2019-03-25 22:25:09 +00:00
}
2019-07-31 18:21:06 +01:00
// BatchUpdateStats updates multiple storagenode's stats in one transaction
2019-08-06 17:35:59 +01:00
func ( service * Service ) BatchUpdateStats ( ctx context . Context , requests [ ] * UpdateRequest ) ( failed storj . NodeIDList , err error ) {
2019-07-31 18:21:06 +01:00
defer mon . Task ( ) ( & ctx ) ( & err )
for _ , request := range requests {
2019-08-06 17:35:59 +01:00
request . AuditLambda = service . config . Node . AuditReputationLambda
request . AuditWeight = service . config . Node . AuditReputationWeight
request . AuditDQ = service . config . Node . AuditReputationDQ
request . UptimeLambda = service . config . Node . UptimeReputationLambda
request . UptimeWeight = service . config . Node . UptimeReputationWeight
request . UptimeDQ = service . config . Node . UptimeReputationDQ
2019-07-31 18:21:06 +01:00
}
2019-08-06 17:35:59 +01:00
return service . db . BatchUpdateStats ( ctx , requests , service . config . UpdateStatsBatchSize )
2019-07-31 18:21:06 +01:00
}
2019-03-25 22:25:09 +00:00
// UpdateStats all parts of single storagenode's stats.
2019-08-06 17:35:59 +01:00
func ( service * Service ) UpdateStats ( ctx context . Context , request * UpdateRequest ) ( stats * NodeStats , err error ) {
2019-03-25 22:25:09 +00:00
defer mon . Task ( ) ( & ctx ) ( & err )
2019-06-20 14:56:04 +01:00
2019-08-06 17:35:59 +01:00
request . AuditLambda = service . config . Node . AuditReputationLambda
request . AuditWeight = service . config . Node . AuditReputationWeight
request . AuditDQ = service . config . Node . AuditReputationDQ
request . UptimeLambda = service . config . Node . UptimeReputationLambda
request . UptimeWeight = service . config . Node . UptimeReputationWeight
request . UptimeDQ = service . config . Node . UptimeReputationDQ
2019-06-20 14:56:04 +01:00
2019-08-06 17:35:59 +01:00
return service . db . UpdateStats ( ctx , request )
2019-03-25 22:25:09 +00:00
}
2019-04-10 07:04:24 +01:00
// UpdateNodeInfo updates node dossier with info requested from the node itself like node type, email, wallet, capacity, and version.
2019-08-06 17:35:59 +01:00
func ( service * Service ) UpdateNodeInfo ( ctx context . Context , node storj . NodeID , nodeInfo * pb . InfoResponse ) ( stats * NodeDossier , err error ) {
2019-03-25 22:25:09 +00:00
defer mon . Task ( ) ( & ctx ) ( & err )
2019-08-06 17:35:59 +01:00
return service . db . UpdateNodeInfo ( ctx , node , nodeInfo )
2019-03-25 22:25:09 +00:00
}
// UpdateUptime updates a single storagenode's uptime stats.
2019-08-06 17:35:59 +01:00
func ( service * Service ) UpdateUptime ( ctx context . Context , nodeID storj . NodeID , isUp bool ) ( stats * NodeStats , err error ) {
2019-03-25 22:25:09 +00:00
defer mon . Task ( ) ( & ctx ) ( & err )
2019-08-06 17:35:59 +01:00
lambda := service . config . Node . UptimeReputationLambda
weight := service . config . Node . UptimeReputationWeight
uptimeDQ := service . config . Node . UptimeReputationDQ
2019-06-20 14:56:04 +01:00
2019-08-06 17:35:59 +01:00
return service . db . UpdateUptime ( ctx , nodeID , isUp , lambda , weight , uptimeDQ )
2019-03-25 22:25:09 +00:00
}
2019-09-19 19:37:31 +01:00
// UpdateCheckIn updates a single storagenode's check-in info.
func ( service * Service ) UpdateCheckIn ( ctx context . Context , node NodeCheckInInfo ) ( err error ) {
defer mon . Task ( ) ( & ctx ) ( & err )
return service . db . UpdateCheckIn ( ctx , node , service . config . Node )
}
2019-05-16 14:49:10 +01:00
// GetMissingPieces returns the list of offline nodes
2019-08-06 17:35:59 +01:00
func ( service * Service ) GetMissingPieces ( ctx context . Context , pieces [ ] * pb . RemotePiece ) ( missingPieces [ ] int32 , err error ) {
2019-06-04 12:36:27 +01:00
defer mon . Task ( ) ( & ctx ) ( & err )
2019-05-16 14:49:10 +01:00
var nodeIDs storj . NodeIDList
for _ , p := range pieces {
nodeIDs = append ( nodeIDs , p . NodeId )
}
2019-08-06 17:35:59 +01:00
badNodeIDs , err := service . KnownUnreliableOrOffline ( ctx , nodeIDs )
2019-05-16 14:49:10 +01:00
if err != nil {
return nil , Error . New ( "error getting nodes %s" , err )
}
for _ , p := range pieces {
for _ , nodeID := range badNodeIDs {
if nodeID == p . NodeId {
missingPieces = append ( missingPieces , p . GetPieceNum ( ) )
}
}
}
return missingPieces , nil
}
2019-05-30 18:35:04 +01:00
2019-06-24 16:33:18 +01:00
func getIP ( ctx context . Context , target string ) ( ip net . IPAddr , err error ) {
2019-06-04 12:36:27 +01:00
defer mon . Task ( ) ( & ctx ) ( & err )
2019-05-30 18:35:04 +01:00
host , _ , err := net . SplitHostPort ( target )
if err != nil {
2019-06-24 16:33:18 +01:00
return net . IPAddr { } , err
2019-05-30 18:35:04 +01:00
}
ipAddr , err := net . ResolveIPAddr ( "ip" , host )
2019-06-24 16:33:18 +01:00
if err != nil {
return net . IPAddr { } , err
}
return * ipAddr , nil
}
// GetNetwork resolves the target address and determines its IP /24 Subnet
func GetNetwork ( ctx context . Context , target string ) ( network string , err error ) {
defer mon . Task ( ) ( & ctx ) ( & err )
addr , err := getIP ( ctx , target )
2019-05-30 18:35:04 +01:00
if err != nil {
return "" , err
}
2019-06-24 16:33:18 +01:00
// If addr can be converted to 4byte notation, it is an IPv4 address, else its an IPv6 address
if ipv4 := addr . IP . To4 ( ) ; ipv4 != nil {
//Filter all IPv4 Addresses into /24 Subnet's
mask := net . CIDRMask ( 24 , 32 )
return ipv4 . Mask ( mask ) . String ( ) , nil
}
if ipv6 := addr . IP . To16 ( ) ; ipv6 != nil {
//Filter all IPv6 Addresses into /64 Subnet's
mask := net . CIDRMask ( 64 , 128 )
return ipv6 . Mask ( mask ) . String ( ) , nil
}
return "" , errors . New ( "unable to get network for address " + addr . String ( ) )
2019-05-30 18:35:04 +01:00
}