github.com/ledgerwatch/erigon-lib@v1.0.0/downloader/downloader_grpc_server.go (about) 1 /* 2 Copyright 2021 Erigon contributors 3 4 Licensed under the Apache License, Version 2.0 (the "License"); 5 you may not use this file except in compliance with the License. 6 You may obtain a copy of the License at 7 8 http://www.apache.org/licenses/LICENSE-2.0 9 10 Unless required by applicable law or agreed to in writing, software 11 distributed under the License is distributed on an "AS IS" BASIS, 12 WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. 13 See the License for the specific language governing permissions and 14 limitations under the License. 15 */ 16 17 package downloader 18 19 import ( 20 "context" 21 "fmt" 22 "time" 23 24 "github.com/anacrolix/torrent/metainfo" 25 "github.com/ledgerwatch/erigon-lib/gointerfaces" 26 proto_downloader "github.com/ledgerwatch/erigon-lib/gointerfaces/downloader" 27 prototypes "github.com/ledgerwatch/erigon-lib/gointerfaces/types" 28 "github.com/ledgerwatch/log/v3" 29 "google.golang.org/protobuf/types/known/emptypb" 30 ) 31 32 var ( 33 _ proto_downloader.DownloaderServer = &GrpcServer{} 34 ) 35 36 func NewGrpcServer(d *Downloader) (*GrpcServer, error) { 37 return &GrpcServer{d: d}, nil 38 } 39 40 type GrpcServer struct { 41 proto_downloader.UnimplementedDownloaderServer 42 d *Downloader 43 } 44 45 // Download - create new .torrent ONLY if initialSync, everything else Erigon can generate by itself 46 func (s *GrpcServer) Download(ctx context.Context, request *proto_downloader.DownloadRequest) (*emptypb.Empty, error) { 47 logEvery := time.NewTicker(20 * time.Second) 48 defer logEvery.Stop() 49 defer s.d.applyWebseeds() 50 51 for i, it := range request.Items { 52 if it.Path == "" { 53 return nil, fmt.Errorf("field 'path' is required") 54 } 55 56 select { 57 case <-logEvery.C: 58 log.Info("[snapshots] initializing", "files", fmt.Sprintf("%d/%d", i, len(request.Items))) 59 default: 60 } 61 62 if it.TorrentHash == nil { 63 // if we don't have the torrent hash then we seed a new snapshot 64 if err := s.d.AddNewSeedableFile(ctx, it.Path); err != nil { 65 return nil, err 66 } 67 continue 68 } 69 70 if err := s.d.AddInfoHashAsMagnetLink(ctx, Proto2InfoHash(it.TorrentHash), it.Path); err != nil { 71 return nil, err 72 } 73 } 74 s.d.ReCalcStats(10 * time.Second) // immediately call ReCalc to set stat.Complete flag 75 return &emptypb.Empty{}, nil 76 } 77 78 func (s *GrpcServer) Verify(ctx context.Context, request *proto_downloader.VerifyRequest) (*emptypb.Empty, error) { 79 err := s.d.VerifyData(ctx) 80 if err != nil { 81 return nil, err 82 } 83 return &emptypb.Empty{}, nil 84 } 85 86 func (s *GrpcServer) Stats(ctx context.Context, request *proto_downloader.StatsRequest) (*proto_downloader.StatsReply, error) { 87 stats := s.d.Stats() 88 return &proto_downloader.StatsReply{ 89 MetadataReady: stats.MetadataReady, 90 FilesTotal: stats.FilesTotal, 91 92 Completed: stats.Completed, 93 Progress: stats.Progress, 94 95 PeersUnique: stats.PeersUnique, 96 ConnectionsTotal: stats.ConnectionsTotal, 97 98 BytesCompleted: stats.BytesCompleted, 99 BytesTotal: stats.BytesTotal, 100 UploadRate: stats.UploadRate, 101 DownloadRate: stats.DownloadRate, 102 }, nil 103 } 104 105 func Proto2InfoHash(in *prototypes.H160) metainfo.Hash { 106 return gointerfaces.ConvertH160toAddress(in) 107 }