2020-08-17 13:26:18 +00:00
|
|
|
package sectorstorage
|
2020-03-23 11:40:02 +00:00
|
|
|
|
|
|
|
import (
|
|
|
|
"context"
|
|
|
|
"io"
|
|
|
|
"os"
|
2020-04-27 12:38:24 +00:00
|
|
|
"runtime"
|
2020-03-23 11:40:02 +00:00
|
|
|
|
|
|
|
"github.com/elastic/go-sysinfo"
|
2020-06-22 15:02:59 +00:00
|
|
|
"github.com/hashicorp/go-multierror"
|
2020-05-14 15:35:38 +00:00
|
|
|
"github.com/ipfs/go-cid"
|
2020-03-23 11:40:02 +00:00
|
|
|
"golang.org/x/xerrors"
|
|
|
|
|
|
|
|
ffi "github.com/filecoin-project/filecoin-ffi"
|
|
|
|
"github.com/filecoin-project/specs-actors/actors/abi"
|
|
|
|
storage2 "github.com/filecoin-project/specs-storage/storage"
|
|
|
|
|
2020-08-17 13:26:18 +00:00
|
|
|
"github.com/filecoin-project/lotus/extern/sector-storage/ffiwrapper"
|
|
|
|
"github.com/filecoin-project/lotus/extern/sector-storage/sealtasks"
|
|
|
|
"github.com/filecoin-project/lotus/extern/sector-storage/stores"
|
|
|
|
"github.com/filecoin-project/lotus/extern/sector-storage/storiface"
|
2020-03-23 11:40:02 +00:00
|
|
|
)
|
|
|
|
|
2020-03-26 02:50:56 +00:00
|
|
|
var pathTypes = []stores.SectorFileType{stores.FTUnsealed, stores.FTSealed, stores.FTCache}
|
2020-03-23 11:40:02 +00:00
|
|
|
|
|
|
|
type WorkerConfig struct {
|
2020-06-15 12:32:17 +00:00
|
|
|
SealProof abi.RegisteredSealProof
|
2020-03-23 11:40:02 +00:00
|
|
|
TaskTypes []sealtasks.TaskType
|
|
|
|
}
|
|
|
|
|
|
|
|
type LocalWorker struct {
|
2020-03-26 02:50:56 +00:00
|
|
|
scfg *ffiwrapper.Config
|
2020-03-23 11:40:02 +00:00
|
|
|
storage stores.Store
|
|
|
|
localStore *stores.Local
|
|
|
|
sindex stores.SectorIndex
|
|
|
|
|
|
|
|
acceptTasks map[sealtasks.TaskType]struct{}
|
|
|
|
}
|
|
|
|
|
|
|
|
func NewLocalWorker(wcfg WorkerConfig, store stores.Store, local *stores.Local, sindex stores.SectorIndex) *LocalWorker {
|
|
|
|
acceptTasks := map[sealtasks.TaskType]struct{}{}
|
|
|
|
for _, taskType := range wcfg.TaskTypes {
|
|
|
|
acceptTasks[taskType] = struct{}{}
|
|
|
|
}
|
|
|
|
|
|
|
|
return &LocalWorker{
|
2020-03-26 02:50:56 +00:00
|
|
|
scfg: &ffiwrapper.Config{
|
2020-03-23 11:40:02 +00:00
|
|
|
SealProofType: wcfg.SealProof,
|
|
|
|
},
|
|
|
|
storage: store,
|
|
|
|
localStore: local,
|
|
|
|
sindex: sindex,
|
|
|
|
|
|
|
|
acceptTasks: acceptTasks,
|
|
|
|
}
|
|
|
|
}
|
|
|
|
|
|
|
|
type localWorkerPathProvider struct {
|
2020-05-26 08:25:29 +00:00
|
|
|
w *LocalWorker
|
2020-05-20 16:36:46 +00:00
|
|
|
op stores.AcquireMode
|
2020-03-23 11:40:02 +00:00
|
|
|
}
|
|
|
|
|
2020-06-04 21:30:20 +00:00
|
|
|
func (l *localWorkerPathProvider) AcquireSector(ctx context.Context, sector abi.SectorID, existing stores.SectorFileType, allocate stores.SectorFileType, sealing stores.PathType) (stores.SectorPaths, func(), error) {
|
2020-07-06 16:36:44 +00:00
|
|
|
|
2020-06-04 21:30:20 +00:00
|
|
|
paths, storageIDs, err := l.w.storage.AcquireSector(ctx, sector, l.w.scfg.SealProofType, existing, allocate, sealing, l.op)
|
2020-03-23 11:40:02 +00:00
|
|
|
if err != nil {
|
2020-03-26 02:50:56 +00:00
|
|
|
return stores.SectorPaths{}, nil, err
|
2020-03-23 11:40:02 +00:00
|
|
|
}
|
|
|
|
|
2020-07-06 16:36:44 +00:00
|
|
|
releaseStorage, err := l.w.localStore.Reserve(ctx, sector, l.w.scfg.SealProofType, allocate, storageIDs, stores.FSOverheadSeal)
|
|
|
|
if err != nil {
|
|
|
|
return stores.SectorPaths{}, nil, xerrors.Errorf("reserving storage space: %w", err)
|
|
|
|
}
|
|
|
|
|
2020-03-23 11:40:02 +00:00
|
|
|
log.Debugf("acquired sector %d (e:%d; a:%d): %v", sector, existing, allocate, paths)
|
|
|
|
|
|
|
|
return paths, func() {
|
2020-07-06 16:36:44 +00:00
|
|
|
releaseStorage()
|
|
|
|
|
2020-03-23 11:40:02 +00:00
|
|
|
for _, fileType := range pathTypes {
|
|
|
|
if fileType&allocate == 0 {
|
|
|
|
continue
|
|
|
|
}
|
|
|
|
|
2020-03-26 02:50:56 +00:00
|
|
|
sid := stores.PathByType(storageIDs, fileType)
|
2020-03-23 11:40:02 +00:00
|
|
|
|
2020-05-20 16:36:46 +00:00
|
|
|
if err := l.w.sindex.StorageDeclareSector(ctx, stores.ID(sid), sector, fileType, l.op == stores.AcquireMove); err != nil {
|
2020-03-23 11:40:02 +00:00
|
|
|
log.Errorf("declare sector error: %+v", err)
|
|
|
|
}
|
|
|
|
}
|
|
|
|
}, nil
|
|
|
|
}
|
|
|
|
|
2020-03-26 19:34:38 +00:00
|
|
|
func (l *LocalWorker) sb() (ffiwrapper.Storage, error) {
|
2020-03-26 02:50:56 +00:00
|
|
|
return ffiwrapper.New(&localWorkerPathProvider{w: l}, l.scfg)
|
2020-03-23 11:40:02 +00:00
|
|
|
}
|
|
|
|
|
|
|
|
func (l *LocalWorker) NewSector(ctx context.Context, sector abi.SectorID) error {
|
|
|
|
sb, err := l.sb()
|
|
|
|
if err != nil {
|
|
|
|
return err
|
|
|
|
}
|
|
|
|
|
|
|
|
return sb.NewSector(ctx, sector)
|
|
|
|
}
|
|
|
|
|
|
|
|
func (l *LocalWorker) AddPiece(ctx context.Context, sector abi.SectorID, epcs []abi.UnpaddedPieceSize, sz abi.UnpaddedPieceSize, r io.Reader) (abi.PieceInfo, error) {
|
|
|
|
sb, err := l.sb()
|
|
|
|
if err != nil {
|
|
|
|
return abi.PieceInfo{}, err
|
|
|
|
}
|
|
|
|
|
|
|
|
return sb.AddPiece(ctx, sector, epcs, sz, r)
|
|
|
|
}
|
|
|
|
|
2020-06-04 21:30:20 +00:00
|
|
|
func (l *LocalWorker) Fetch(ctx context.Context, sector abi.SectorID, fileType stores.SectorFileType, ptype stores.PathType, am stores.AcquireMode) error {
|
|
|
|
_, done, err := (&localWorkerPathProvider{w: l, op: am}).AcquireSector(ctx, sector, fileType, stores.FTNone, ptype)
|
2020-04-27 12:55:37 +00:00
|
|
|
if err != nil {
|
|
|
|
return err
|
|
|
|
}
|
|
|
|
done()
|
|
|
|
return nil
|
|
|
|
}
|
|
|
|
|
2020-03-23 11:40:02 +00:00
|
|
|
func (l *LocalWorker) SealPreCommit1(ctx context.Context, sector abi.SectorID, ticket abi.SealRandomness, pieces []abi.PieceInfo) (out storage2.PreCommit1Out, err error) {
|
2020-05-13 18:45:14 +00:00
|
|
|
{
|
|
|
|
// cleanup previous failed attempts if they exist
|
|
|
|
if err := l.storage.Remove(ctx, sector, stores.FTSealed, true); err != nil {
|
|
|
|
return nil, xerrors.Errorf("cleaning up sealed data: %w", err)
|
|
|
|
}
|
|
|
|
|
|
|
|
if err := l.storage.Remove(ctx, sector, stores.FTCache, true); err != nil {
|
|
|
|
return nil, xerrors.Errorf("cleaning up cache data: %w", err)
|
|
|
|
}
|
|
|
|
}
|
|
|
|
|
2020-03-23 11:40:02 +00:00
|
|
|
sb, err := l.sb()
|
|
|
|
if err != nil {
|
|
|
|
return nil, err
|
|
|
|
}
|
|
|
|
|
|
|
|
return sb.SealPreCommit1(ctx, sector, ticket, pieces)
|
|
|
|
}
|
|
|
|
|
|
|
|
func (l *LocalWorker) SealPreCommit2(ctx context.Context, sector abi.SectorID, phase1Out storage2.PreCommit1Out) (cids storage2.SectorCids, err error) {
|
|
|
|
sb, err := l.sb()
|
|
|
|
if err != nil {
|
|
|
|
return storage2.SectorCids{}, err
|
|
|
|
}
|
|
|
|
|
|
|
|
return sb.SealPreCommit2(ctx, sector, phase1Out)
|
|
|
|
}
|
|
|
|
|
|
|
|
func (l *LocalWorker) SealCommit1(ctx context.Context, sector abi.SectorID, ticket abi.SealRandomness, seed abi.InteractiveSealRandomness, pieces []abi.PieceInfo, cids storage2.SectorCids) (output storage2.Commit1Out, err error) {
|
|
|
|
sb, err := l.sb()
|
|
|
|
if err != nil {
|
|
|
|
return nil, err
|
|
|
|
}
|
|
|
|
|
|
|
|
return sb.SealCommit1(ctx, sector, ticket, seed, pieces, cids)
|
|
|
|
}
|
|
|
|
|
|
|
|
func (l *LocalWorker) SealCommit2(ctx context.Context, sector abi.SectorID, phase1Out storage2.Commit1Out) (proof storage2.Proof, err error) {
|
|
|
|
sb, err := l.sb()
|
|
|
|
if err != nil {
|
|
|
|
return nil, err
|
|
|
|
}
|
|
|
|
|
|
|
|
return sb.SealCommit2(ctx, sector, phase1Out)
|
|
|
|
}
|
|
|
|
|
2020-06-22 15:02:59 +00:00
|
|
|
func (l *LocalWorker) FinalizeSector(ctx context.Context, sector abi.SectorID, keepUnsealed []storage2.Range) error {
|
2020-03-23 11:40:02 +00:00
|
|
|
sb, err := l.sb()
|
|
|
|
if err != nil {
|
|
|
|
return err
|
|
|
|
}
|
|
|
|
|
2020-06-22 15:02:59 +00:00
|
|
|
if err := sb.FinalizeSector(ctx, sector, keepUnsealed); err != nil {
|
2020-03-24 20:28:07 +00:00
|
|
|
return xerrors.Errorf("finalizing sector: %w", err)
|
|
|
|
}
|
|
|
|
|
2020-07-03 19:52:31 +00:00
|
|
|
if len(keepUnsealed) == 0 {
|
|
|
|
if err := l.storage.Remove(ctx, sector, stores.FTUnsealed, true); err != nil {
|
|
|
|
return xerrors.Errorf("removing unsealed data: %w", err)
|
|
|
|
}
|
2020-03-24 20:28:07 +00:00
|
|
|
}
|
|
|
|
|
2020-06-03 21:44:59 +00:00
|
|
|
return nil
|
|
|
|
}
|
|
|
|
|
2020-06-22 15:02:59 +00:00
|
|
|
func (l *LocalWorker) ReleaseUnsealed(ctx context.Context, sector abi.SectorID, safeToFree []storage2.Range) error {
|
|
|
|
return xerrors.Errorf("implement me")
|
|
|
|
}
|
|
|
|
|
|
|
|
func (l *LocalWorker) Remove(ctx context.Context, sector abi.SectorID) error {
|
|
|
|
var err error
|
|
|
|
|
|
|
|
if rerr := l.storage.Remove(ctx, sector, stores.FTSealed, true); rerr != nil {
|
|
|
|
err = multierror.Append(err, xerrors.Errorf("removing sector (sealed): %w", rerr))
|
|
|
|
}
|
|
|
|
if rerr := l.storage.Remove(ctx, sector, stores.FTCache, true); rerr != nil {
|
|
|
|
err = multierror.Append(err, xerrors.Errorf("removing sector (cache): %w", rerr))
|
|
|
|
}
|
|
|
|
if rerr := l.storage.Remove(ctx, sector, stores.FTUnsealed, true); rerr != nil {
|
|
|
|
err = multierror.Append(err, xerrors.Errorf("removing sector (unsealed): %w", rerr))
|
|
|
|
}
|
|
|
|
|
|
|
|
return err
|
|
|
|
}
|
|
|
|
|
2020-08-31 10:44:24 +00:00
|
|
|
func (l *LocalWorker) MoveStorage(ctx context.Context, sector abi.SectorID, types stores.SectorFileType) error {
|
|
|
|
if err := l.storage.MoveStorage(ctx, sector, l.scfg.SealProofType, types); err != nil {
|
2020-03-25 18:21:53 +00:00
|
|
|
return xerrors.Errorf("moving sealed data to storage: %w", err)
|
|
|
|
}
|
|
|
|
|
2020-03-24 20:28:07 +00:00
|
|
|
return nil
|
2020-03-23 11:40:02 +00:00
|
|
|
}
|
|
|
|
|
2020-05-26 08:25:17 +00:00
|
|
|
func (l *LocalWorker) UnsealPiece(ctx context.Context, sector abi.SectorID, index storiface.UnpaddedByteIndex, size abi.UnpaddedPieceSize, randomness abi.SealRandomness, cid cid.Cid) error {
|
2020-05-20 16:36:46 +00:00
|
|
|
sb, err := l.sb()
|
|
|
|
if err != nil {
|
|
|
|
return err
|
|
|
|
}
|
|
|
|
|
|
|
|
if err := sb.UnsealPiece(ctx, sector, index, size, randomness, cid); err != nil {
|
|
|
|
return xerrors.Errorf("unsealing sector: %w", err)
|
|
|
|
}
|
|
|
|
|
2020-05-29 16:57:44 +00:00
|
|
|
if err := l.storage.RemoveCopies(ctx, sector, stores.FTSealed); err != nil {
|
|
|
|
return xerrors.Errorf("removing source data: %w", err)
|
|
|
|
}
|
|
|
|
|
|
|
|
if err := l.storage.RemoveCopies(ctx, sector, stores.FTCache); err != nil {
|
2020-05-20 16:36:46 +00:00
|
|
|
return xerrors.Errorf("removing source data: %w", err)
|
|
|
|
}
|
|
|
|
|
|
|
|
return nil
|
2020-05-14 15:35:38 +00:00
|
|
|
}
|
|
|
|
|
2020-07-30 20:03:43 +00:00
|
|
|
func (l *LocalWorker) ReadPiece(ctx context.Context, writer io.Writer, sector abi.SectorID, index storiface.UnpaddedByteIndex, size abi.UnpaddedPieceSize) (bool, error) {
|
2020-05-20 16:36:46 +00:00
|
|
|
sb, err := l.sb()
|
|
|
|
if err != nil {
|
2020-07-30 20:03:43 +00:00
|
|
|
return false, err
|
2020-05-20 16:36:46 +00:00
|
|
|
}
|
|
|
|
|
|
|
|
return sb.ReadPiece(ctx, writer, sector, index, size)
|
2020-05-14 15:35:38 +00:00
|
|
|
}
|
|
|
|
|
2020-03-23 11:40:02 +00:00
|
|
|
func (l *LocalWorker) TaskTypes(context.Context) (map[sealtasks.TaskType]struct{}, error) {
|
|
|
|
return l.acceptTasks, nil
|
|
|
|
}
|
|
|
|
|
|
|
|
func (l *LocalWorker) Paths(ctx context.Context) ([]stores.StoragePath, error) {
|
|
|
|
return l.localStore.Local(ctx)
|
|
|
|
}
|
|
|
|
|
2020-04-23 22:16:21 +00:00
|
|
|
func (l *LocalWorker) Info(context.Context) (storiface.WorkerInfo, error) {
|
2020-03-23 11:40:02 +00:00
|
|
|
hostname, err := os.Hostname() // TODO: allow overriding from config
|
|
|
|
if err != nil {
|
|
|
|
panic(err)
|
|
|
|
}
|
|
|
|
|
|
|
|
gpus, err := ffi.GetGPUDevices()
|
|
|
|
if err != nil {
|
|
|
|
log.Errorf("getting gpu devices failed: %+v", err)
|
|
|
|
}
|
|
|
|
|
|
|
|
h, err := sysinfo.Host()
|
|
|
|
if err != nil {
|
2020-04-23 22:16:21 +00:00
|
|
|
return storiface.WorkerInfo{}, xerrors.Errorf("getting host info: %w", err)
|
2020-03-23 11:40:02 +00:00
|
|
|
}
|
|
|
|
|
|
|
|
mem, err := h.Memory()
|
|
|
|
if err != nil {
|
2020-04-23 22:16:21 +00:00
|
|
|
return storiface.WorkerInfo{}, xerrors.Errorf("getting memory info: %w", err)
|
2020-03-23 11:40:02 +00:00
|
|
|
}
|
|
|
|
|
2020-04-23 22:16:21 +00:00
|
|
|
return storiface.WorkerInfo{
|
2020-03-23 11:40:02 +00:00
|
|
|
Hostname: hostname,
|
2020-04-23 22:16:21 +00:00
|
|
|
Resources: storiface.WorkerResources{
|
2020-03-23 11:40:02 +00:00
|
|
|
MemPhysical: mem.Total,
|
|
|
|
MemSwap: mem.VirtualTotal,
|
|
|
|
MemReserved: mem.VirtualUsed + mem.Total - mem.Available, // TODO: sub this process
|
2020-04-27 12:38:24 +00:00
|
|
|
CPUs: uint64(runtime.NumCPU()),
|
2020-03-23 11:40:02 +00:00
|
|
|
GPUs: gpus,
|
|
|
|
},
|
|
|
|
}, nil
|
|
|
|
}
|
|
|
|
|
2020-05-01 18:00:17 +00:00
|
|
|
func (l *LocalWorker) Closing(ctx context.Context) (<-chan struct{}, error) {
|
|
|
|
return make(chan struct{}), nil
|
|
|
|
}
|
|
|
|
|
2020-03-24 23:49:45 +00:00
|
|
|
func (l *LocalWorker) Close() error {
|
|
|
|
return nil
|
|
|
|
}
|
|
|
|
|
2020-03-23 11:40:02 +00:00
|
|
|
var _ Worker = &LocalWorker{}
|