dragonfly/scheduler/resource/host.go

193 lines
4.4 KiB
Go

/*
* Copyright 2020 The Dragonfly Authors
*
* Licensed under the Apache License, Version 2.0 (the "License");
* you may not use this file except in compliance with the License.
* You may obtain a copy of the License at
*
* http://www.apache.org/licenses/LICENSE-2.0
*
* Unless required by applicable law or agreed to in writing, software
* distributed under the License is distributed on an "AS IS" BASIS,
* WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
* See the License for the specific language governing permissions and
* limitations under the License.
*/
package resource
import (
"sync"
"time"
"go.uber.org/atomic"
logger "d7y.io/dragonfly/v2/internal/dflog"
"d7y.io/dragonfly/v2/pkg/rpc/scheduler"
"d7y.io/dragonfly/v2/scheduler/config"
)
// HostOption is a functional option for configuring the host
type HostOption func(h *Host) *Host
// WithUploadLoadLimit sets host's UploadLoadLimit
func WithUploadLoadLimit(limit int32) HostOption {
return func(h *Host) *Host {
h.UploadLoadLimit.Store(limit)
return h
}
}
// WithIsCDN sets host's IsCDN
func WithIsCDN(isCDN bool) HostOption {
return func(h *Host) *Host {
h.IsCDN = isCDN
return h
}
}
type Host struct {
// ID is host id
ID string
// IP is host ip
IP string
// Hostname is host name
Hostname string
// Port is grpc service port
Port int32
// DownloadPort is piece downloading port
DownloadPort int32
// SecurityDomain is security domain of host
SecurityDomain string
// IDC is internet data center of host
IDC string
// NetTopology is network topology of host
// Example: switch|router|...
NetTopology string
// Location is location of host
// Example: country|province|...
Location string
// UploadLoadLimit is upload load limit count
UploadLoadLimit *atomic.Int32
// UploadPeerCount is upload peer count
UploadPeerCount *atomic.Int32
// Peer sync map
Peers *sync.Map
// PeerCount is peer count
PeerCount *atomic.Int32
// IsCDN is used as tag cdn
IsCDN bool
// CreateAt is host create time
CreateAt *atomic.Time
// UpdateAt is host update time
UpdateAt *atomic.Time
// Host log
Log *logger.SugaredLoggerOnWith
}
// New host instance
func NewHost(rawHost *scheduler.PeerHost, options ...HostOption) *Host {
h := &Host{
ID: rawHost.Uuid,
IP: rawHost.Ip,
Hostname: rawHost.HostName,
Port: rawHost.RpcPort,
DownloadPort: rawHost.DownPort,
SecurityDomain: rawHost.SecurityDomain,
IDC: rawHost.Idc,
NetTopology: rawHost.NetTopology,
Location: rawHost.Location,
UploadLoadLimit: atomic.NewInt32(config.DefaultClientLoadLimit),
UploadPeerCount: atomic.NewInt32(0),
Peers: &sync.Map{},
PeerCount: atomic.NewInt32(0),
IsCDN: false,
CreateAt: atomic.NewTime(time.Now()),
UpdateAt: atomic.NewTime(time.Now()),
Log: logger.WithHostID(rawHost.Uuid),
}
for _, opt := range options {
opt(h)
}
return h
}
// LoadPeer return peer for a key
func (h *Host) LoadPeer(key string) (*Peer, bool) {
rawPeer, ok := h.Peers.Load(key)
if !ok {
return nil, false
}
return rawPeer.(*Peer), ok
}
// StorePeer set peer
func (h *Host) StorePeer(peer *Peer) {
h.Peers.Store(peer.ID, peer)
h.PeerCount.Inc()
}
// LoadOrStorePeer returns peer the key if present.
// Otherwise, it stores and returns the given peer.
// The loaded result is true if the peer was loaded, false if stored.
func (h *Host) LoadOrStorePeer(peer *Peer) (*Peer, bool) {
rawPeer, loaded := h.Peers.LoadOrStore(peer.ID, peer)
if !loaded {
h.PeerCount.Inc()
}
return rawPeer.(*Peer), loaded
}
// DeletePeer deletes peer for a key
func (h *Host) DeletePeer(key string) {
if _, loaded := h.Peers.LoadAndDelete(key); loaded {
h.PeerCount.Dec()
}
}
// LeavePeers set peer state to PeerStateLeave
func (h *Host) LeavePeers() {
h.Peers.Range(func(_, value interface{}) bool {
if peer, ok := value.(*Peer); ok {
if err := peer.FSM.Event(PeerEventDownloadFailed); err != nil {
peer.Log.Errorf("peer fsm event failed: %v", err)
return true
}
if err := peer.FSM.Event(PeerEventLeave); err != nil {
peer.Log.Errorf("peer fsm event failed: %v", err)
return true
}
h.Log.Infof("peer %s has been left", peer.ID)
}
return true
})
}
// FreeUploadLoad return free upload load of host
func (h *Host) FreeUploadLoad() int32 {
return h.UploadLoadLimit.Load() - h.UploadPeerCount.Load()
}