storj/pkg/datarepair/checker/online.go

75 lines
1.9 KiB
Go

// Copyright (C) 2019 Storj Labs, Inc.
// See LICENSE for copying information.
package checker
import (
"context"
"time"
"storj.io/storj/pkg/overlay"
"storj.io/storj/pkg/pb"
"storj.io/storj/pkg/storj"
)
// ReliabilityCache caches the reliable nodes for the specified staleness duration
// and updates automatically from overlay.
//
// ReliabilityCache is NOT safe for concurrent use.
type ReliabilityCache struct {
overlay *overlay.Cache
staleness time.Duration
lastUpdate time.Time
reliable map[storj.NodeID]struct{}
}
// NewReliabilityCache creates a new reliability checking cache.
func NewReliabilityCache(overlay *overlay.Cache, staleness time.Duration) *ReliabilityCache {
return &ReliabilityCache{
overlay: overlay,
staleness: staleness,
reliable: map[storj.NodeID]struct{}{},
}
}
// LastUpdate returns when the cache was last updated.
func (cache *ReliabilityCache) LastUpdate() time.Time { return cache.lastUpdate }
// MissingPieces returns piece indices that are unreliable with the given staleness period.
func (cache *ReliabilityCache) MissingPieces(ctx context.Context, created time.Time, pieces []*pb.RemotePiece) ([]int32, error) {
if created.After(cache.lastUpdate) || time.Since(cache.lastUpdate) > cache.staleness {
err := cache.Refresh(ctx)
if err != nil {
return nil, err
}
}
var unreliable []int32
for _, piece := range pieces {
if _, ok := cache.reliable[piece.NodeId]; !ok {
unreliable = append(unreliable, piece.PieceNum)
}
}
return unreliable, nil
}
// Refresh refreshes the cache.
func (cache *ReliabilityCache) Refresh(ctx context.Context) error {
for id := range cache.reliable {
delete(cache.reliable, id)
}
cache.lastUpdate = time.Now()
nodes, err := cache.overlay.Reliable(ctx)
if err != nil {
return Error.Wrap(err)
}
for _, id := range nodes {
cache.reliable[id] = struct{}{}
}
return nil
}