forked from NebulousLabs/Sia
-
Notifications
You must be signed in to change notification settings - Fork 0
/
renter.go
109 lines (89 loc) · 2.81 KB
/
renter.go
1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
20
21
22
23
24
25
26
27
28
29
30
31
32
33
34
35
36
37
38
39
40
41
42
43
44
45
46
47
48
49
50
51
52
53
54
55
56
57
58
59
60
61
62
63
64
65
66
67
68
69
70
71
72
73
74
75
76
77
78
79
80
81
82
83
84
85
86
87
88
89
90
91
92
93
94
95
96
97
98
99
100
101
102
103
104
105
106
107
108
109
package renter
import (
"errors"
"os"
"github.com/NebulousLabs/Sia/modules"
"github.com/NebulousLabs/Sia/modules/consensus"
"github.com/NebulousLabs/Sia/sync"
"github.com/NebulousLabs/Sia/types"
)
var (
ErrNilCS = errors.New("cannot create renter with nil consensus set")
ErrNilHostDB = errors.New("cannot create renter with nil hostdb")
ErrNilWallet = errors.New("cannot create renter wil nil wlalet")
)
// A Renter is responsible for tracking all of the files that a user has
// uploaded to Sia, as well as the locations and health of these files.
type Renter struct {
cs *consensus.State
hostDB modules.HostDB
wallet modules.Wallet
blockHeight types.BlockHeight
files map[string]*file
downloadQueue []*Download
saveDir string
subscriptions []chan struct{}
mu *sync.RWMutex
}
// New returns an empty renter.
func New(cs *consensus.State, hdb modules.HostDB, wallet modules.Wallet, saveDir string) (*Renter, error) {
if cs == nil {
return nil, ErrNilCS
}
if hdb == nil {
return nil, ErrNilHostDB
}
if wallet == nil {
return nil, ErrNilWallet
}
r := &Renter{
cs: cs,
hostDB: hdb,
wallet: wallet,
files: make(map[string]*file),
saveDir: saveDir,
mu: sync.New(modules.SafeMutexDelay, 1),
}
err := os.MkdirAll(saveDir, 0700)
if err != nil {
return nil, err
}
r.load()
// TODO: I'm worried about balances here. Because of the way that the
// re-try algorithm works, it won't be a problem, but without that we would
// need to make sure that scanAllFiles() didn't get called until the entire
// balance had loaded, which would require loading the entire blockchain.
// This also won't be a problem once we're also saving the addresses.
//
// TODO: bring back this functionality when we have resumable uploads.
//r.scanAllFiles()
r.cs.ConsensusSetSubscribe(r)
return r, nil
}
// Info returns generic information about the renter and the files that are
// being rented.
func (r *Renter) Info() (ri modules.RentInfo) {
lockID := r.mu.RLock()
defer r.mu.RUnlock(lockID)
// Include the list of files the renter knows about.
for filename := range r.files {
ri.Files = append(ri.Files, filename)
}
// Calculate the average cost of a file.
var averagePrice types.Currency
sampleSize := redundancy * 2
hosts := r.hostDB.RandomHosts(sampleSize)
for _, host := range hosts {
averagePrice = averagePrice.Add(host.Price)
}
if len(hosts) == 0 {
return
}
averagePrice = averagePrice.Div(types.NewCurrency64(uint64(len(hosts))))
// HACK: 6000 is the duration (set by the API), and 1024^3 is a GB. Price
// is reported as per GB, no timeframe is given.
estimatedCost := averagePrice.Mul(types.NewCurrency64(6000)).Mul(types.NewCurrency64(1024 * 1024 * 1024))
bufferedCost := estimatedCost.Mul(types.NewCurrency64(2))
ri.Price = bufferedCost
return
}