workers: Transfer logic refactoring
This commit is contained in:
parent
eb61a36fd7
commit
7e2e30f94b
@ -134,6 +134,16 @@ type StorageInfo struct {
|
|||||||
CanStore bool
|
CanStore bool
|
||||||
}
|
}
|
||||||
|
|
||||||
|
type StoragePath struct {
|
||||||
|
ID string
|
||||||
|
Weight uint64
|
||||||
|
|
||||||
|
LocalPath string
|
||||||
|
|
||||||
|
CanSeal bool
|
||||||
|
CanStore bool
|
||||||
|
}
|
||||||
|
|
||||||
type SealRes struct {
|
type SealRes struct {
|
||||||
Err string
|
Err string
|
||||||
GoErr error `json:"-"`
|
GoErr error `json:"-"`
|
||||||
|
@ -14,6 +14,7 @@ type WorkerApi interface {
|
|||||||
// TODO: Info() (name, ...) ?
|
// TODO: Info() (name, ...) ?
|
||||||
|
|
||||||
TaskTypes(context.Context) (map[sealmgr.TaskType]struct{}, error) // TaskType -> Weight
|
TaskTypes(context.Context) (map[sealmgr.TaskType]struct{}, error) // TaskType -> Weight
|
||||||
|
Paths(context.Context) ([]StoragePath, error)
|
||||||
|
|
||||||
storage.Sealer
|
storage.Sealer
|
||||||
}
|
}
|
||||||
|
@ -199,6 +199,7 @@ type WorkerStruct struct {
|
|||||||
Version func(context.Context) (build.Version, error) `perm:"admin"`
|
Version func(context.Context) (build.Version, error) `perm:"admin"`
|
||||||
|
|
||||||
TaskTypes func(context.Context) (map[sealmgr.TaskType]struct{}, error) `perm:"admin"`
|
TaskTypes func(context.Context) (map[sealmgr.TaskType]struct{}, error) `perm:"admin"`
|
||||||
|
Paths func(context.Context) ([]api.StoragePath, error) `perm:"admin"`
|
||||||
|
|
||||||
SealPreCommit1 func(ctx context.Context, sectorNum abi.SectorNumber, ticket abi.SealRandomness, pieces []abi.PieceInfo) (storage.PreCommit1Out, error) `perm:"admin"`
|
SealPreCommit1 func(ctx context.Context, sectorNum abi.SectorNumber, ticket abi.SealRandomness, pieces []abi.PieceInfo) (storage.PreCommit1Out, error) `perm:"admin"`
|
||||||
SealPreCommit2 func(context.Context, abi.SectorNumber, storage.PreCommit1Out) (sealedCID cid.Cid, unsealedCID cid.Cid, err error) `perm:"admin"`
|
SealPreCommit2 func(context.Context, abi.SectorNumber, storage.PreCommit1Out) (sealedCID cid.Cid, unsealedCID cid.Cid, err error) `perm:"admin"`
|
||||||
@ -698,6 +699,10 @@ func (w *WorkerStruct) TaskTypes(ctx context.Context) (map[sealmgr.TaskType]stru
|
|||||||
return w.Internal.TaskTypes(ctx)
|
return w.Internal.TaskTypes(ctx)
|
||||||
}
|
}
|
||||||
|
|
||||||
|
func (w *WorkerStruct) Paths(ctx context.Context) ([]api.StoragePath, error) {
|
||||||
|
return w.Internal.Paths(ctx)
|
||||||
|
}
|
||||||
|
|
||||||
func (w *WorkerStruct) SealPreCommit1(ctx context.Context, sectorNum abi.SectorNumber, ticket abi.SealRandomness, pieces []abi.PieceInfo) (storage.PreCommit1Out, error) {
|
func (w *WorkerStruct) SealPreCommit1(ctx context.Context, sectorNum abi.SectorNumber, ticket abi.SealRandomness, pieces []abi.PieceInfo) (storage.PreCommit1Out, error) {
|
||||||
return w.Internal.SealPreCommit1(ctx, sectorNum, ticket, pieces)
|
return w.Internal.SealPreCommit1(ctx, sectorNum, ticket, pieces)
|
||||||
}
|
}
|
||||||
|
@ -3,13 +3,14 @@ package main
|
|||||||
import (
|
import (
|
||||||
"context"
|
"context"
|
||||||
|
|
||||||
|
"github.com/ipfs/go-cid"
|
||||||
|
|
||||||
"github.com/filecoin-project/specs-actors/actors/abi"
|
"github.com/filecoin-project/specs-actors/actors/abi"
|
||||||
"github.com/filecoin-project/specs-storage/storage"
|
"github.com/filecoin-project/specs-storage/storage"
|
||||||
"github.com/ipfs/go-cid"
|
|
||||||
)
|
)
|
||||||
|
|
||||||
type worker struct {
|
type worker struct {
|
||||||
|
spt abi.RegisteredProof
|
||||||
}
|
}
|
||||||
|
|
||||||
func (w *worker) SealPreCommit1(ctx context.Context, sectorNum abi.SectorNumber, ticket abi.SealRandomness, pieces []abi.PieceInfo) (storage.PreCommit1Out, error) {
|
func (w *worker) SealPreCommit1(ctx context.Context, sectorNum abi.SectorNumber, ticket abi.SealRandomness, pieces []abi.PieceInfo) (storage.PreCommit1Out, error) {
|
||||||
|
@ -2,6 +2,8 @@ package main
|
|||||||
|
|
||||||
import (
|
import (
|
||||||
"context"
|
"context"
|
||||||
|
"net/http"
|
||||||
|
"sort"
|
||||||
|
|
||||||
"github.com/filecoin-project/specs-actors/actors/abi"
|
"github.com/filecoin-project/specs-actors/actors/abi"
|
||||||
|
|
||||||
@ -11,12 +13,32 @@ import (
|
|||||||
|
|
||||||
type workerStorage struct {
|
type workerStorage struct {
|
||||||
path string // TODO: multi-path support
|
path string // TODO: multi-path support
|
||||||
|
mid abi.ActorID
|
||||||
|
|
||||||
|
auth http.Header
|
||||||
api api.StorageMiner
|
api api.StorageMiner
|
||||||
}
|
}
|
||||||
|
|
||||||
func (w *workerStorage) AcquireSector(ctx context.Context, id abi.SectorNumber, existing sectorbuilder.SectorFileType, allocate sectorbuilder.SectorFileType, sealing bool) (sectorbuilder.SectorPaths, func(), error) {
|
func (w *workerStorage) AcquireSector(ctx context.Context, id abi.SectorNumber, existing sectorbuilder.SectorFileType, allocate sectorbuilder.SectorFileType, sealing bool) (sectorbuilder.SectorPaths, func(), error) {
|
||||||
w.api.WorkerFindSector()
|
asid := abi.SectorID{
|
||||||
|
Miner: w.mid,
|
||||||
|
Number: id,
|
||||||
|
}
|
||||||
|
|
||||||
|
// extract local storage; prefer
|
||||||
|
|
||||||
|
si, err := w.api.WorkerFindSector(ctx, asid, existing)
|
||||||
|
if err != nil {
|
||||||
|
return sectorbuilder.SectorPaths{}, nil, err
|
||||||
|
}
|
||||||
|
|
||||||
|
sort.Slice(si, func(i, j int) bool {
|
||||||
|
return si[i].Cost < si[j].Cost
|
||||||
|
})
|
||||||
|
|
||||||
|
best := si[0].URLs // TODO: not necessarily true
|
||||||
|
|
||||||
|
w.fetch(best, )
|
||||||
}
|
}
|
||||||
|
|
||||||
var _ sectorbuilder.SectorProvider = &workerStorage{}
|
var _ sectorbuilder.SectorProvider = &workerStorage{}
|
||||||
|
@ -1,37 +1,19 @@
|
|||||||
package main
|
package main
|
||||||
|
|
||||||
/*
|
|
||||||
import (
|
import (
|
||||||
"fmt"
|
|
||||||
"io"
|
|
||||||
"mime"
|
"mime"
|
||||||
"net/http"
|
"net/http"
|
||||||
"os"
|
"os"
|
||||||
|
|
||||||
sectorbuilder "github.com/filecoin-project/go-sectorbuilder"
|
|
||||||
"github.com/filecoin-project/go-sectorbuilder/fs"
|
|
||||||
"github.com/filecoin-project/specs-actors/actors/abi"
|
|
||||||
files "github.com/ipfs/go-ipfs-files"
|
files "github.com/ipfs/go-ipfs-files"
|
||||||
"golang.org/x/xerrors"
|
"golang.org/x/xerrors"
|
||||||
"gopkg.in/cheggaaa/pb.v1"
|
|
||||||
"path/filepath"
|
|
||||||
|
|
||||||
"github.com/filecoin-project/lotus/lib/tarutil"
|
"github.com/filecoin-project/lotus/lib/tarutil"
|
||||||
)
|
)
|
||||||
|
|
||||||
func (w *worker) sizeForType(typ string) int64 {
|
func (w *workerStorage) fetch(url, outname string) error {
|
||||||
size := int64(w.sb.SectorSize())
|
log.Infof("Fetch %s", url)
|
||||||
if typ == "cache" {
|
|
||||||
size *= 10
|
|
||||||
}
|
|
||||||
return size
|
|
||||||
}
|
|
||||||
|
|
||||||
func (w *worker) fetch(typ string, sectorID abi.SectorNumber) error {
|
|
||||||
outname := filepath.Join(w.repo, typ, w.sb.SectorName(sectorID))
|
|
||||||
|
|
||||||
url := w.minerEndpoint + "/remote/" + typ + "/" + fmt.Sprint(sectorID)
|
|
||||||
log.Infof("Fetch %s %s", typ, url)
|
|
||||||
|
|
||||||
req, err := http.NewRequest("GET", url, nil)
|
req, err := http.NewRequest("GET", url, nil)
|
||||||
if err != nil {
|
if err != nil {
|
||||||
@ -49,7 +31,7 @@ func (w *worker) fetch(typ string, sectorID abi.SectorNumber) error {
|
|||||||
return xerrors.Errorf("non-200 code: %d", resp.StatusCode)
|
return xerrors.Errorf("non-200 code: %d", resp.StatusCode)
|
||||||
}
|
}
|
||||||
|
|
||||||
bar := pb.New64(w.sizeForType(typ))
|
/*bar := pb.New64(w.sizeForType(typ))
|
||||||
bar.ShowPercent = true
|
bar.ShowPercent = true
|
||||||
bar.ShowSpeed = true
|
bar.ShowSpeed = true
|
||||||
bar.Units = pb.U_BYTES
|
bar.Units = pb.U_BYTES
|
||||||
@ -57,7 +39,7 @@ func (w *worker) fetch(typ string, sectorID abi.SectorNumber) error {
|
|||||||
barreader := bar.NewProxyReader(resp.Body)
|
barreader := bar.NewProxyReader(resp.Body)
|
||||||
|
|
||||||
bar.Start()
|
bar.Start()
|
||||||
defer bar.Finish()
|
defer bar.Finish()*/
|
||||||
|
|
||||||
mediatype, _, err := mime.ParseMediaType(resp.Header.Get("Content-Type"))
|
mediatype, _, err := mime.ParseMediaType(resp.Header.Get("Content-Type"))
|
||||||
if err != nil {
|
if err != nil {
|
||||||
@ -70,109 +52,11 @@ func (w *worker) fetch(typ string, sectorID abi.SectorNumber) error {
|
|||||||
|
|
||||||
switch mediatype {
|
switch mediatype {
|
||||||
case "application/x-tar":
|
case "application/x-tar":
|
||||||
return tarutil.ExtractTar(barreader, outname)
|
return tarutil.ExtractTar(resp.Body, outname)
|
||||||
case "application/octet-stream":
|
case "application/octet-stream":
|
||||||
return files.WriteTo(files.NewReaderFile(barreader), outname)
|
return files.WriteTo(files.NewReaderFile(resp.Body), outname)
|
||||||
default:
|
default:
|
||||||
return xerrors.Errorf("unknown content type: '%s'", mediatype)
|
return xerrors.Errorf("unknown content type: '%s'", mediatype)
|
||||||
}
|
}
|
||||||
|
|
||||||
}
|
}
|
||||||
|
|
||||||
func (w *worker) push(typ string, sectorID abi.SectorNumber) error {
|
|
||||||
w.limiter.transferLimit <- struct{}{}
|
|
||||||
defer func() {
|
|
||||||
<-w.limiter.transferLimit
|
|
||||||
}()
|
|
||||||
|
|
||||||
filename, err := w.sb.SectorPath(fs.DataType(typ), sectorID)
|
|
||||||
if err != nil {
|
|
||||||
return err
|
|
||||||
}
|
|
||||||
|
|
||||||
url := w.minerEndpoint + "/remote/" + typ + "/" + fmt.Sprint(sectorID)
|
|
||||||
log.Infof("Push %s %s", typ, url)
|
|
||||||
|
|
||||||
stat, err := os.Stat(string(filename))
|
|
||||||
if err != nil {
|
|
||||||
return err
|
|
||||||
}
|
|
||||||
|
|
||||||
var r io.Reader
|
|
||||||
if stat.IsDir() {
|
|
||||||
r, err = tarutil.TarDirectory(string(filename))
|
|
||||||
} else {
|
|
||||||
r, err = os.OpenFile(string(filename), os.O_RDONLY, 0644)
|
|
||||||
}
|
|
||||||
if err != nil {
|
|
||||||
return xerrors.Errorf("opening push reader: %w", err)
|
|
||||||
}
|
|
||||||
|
|
||||||
bar := pb.New64(w.sizeForType(typ))
|
|
||||||
bar.ShowPercent = true
|
|
||||||
bar.ShowSpeed = true
|
|
||||||
bar.ShowCounters = true
|
|
||||||
bar.Units = pb.U_BYTES
|
|
||||||
|
|
||||||
bar.Start()
|
|
||||||
defer bar.Finish()
|
|
||||||
//todo set content size
|
|
||||||
|
|
||||||
header := w.auth
|
|
||||||
|
|
||||||
if stat.IsDir() {
|
|
||||||
header.Set("Content-Type", "application/x-tar")
|
|
||||||
} else {
|
|
||||||
header.Set("Content-Type", "application/octet-stream")
|
|
||||||
}
|
|
||||||
|
|
||||||
req, err := http.NewRequest("PUT", url, bar.NewProxyReader(r))
|
|
||||||
if err != nil {
|
|
||||||
return err
|
|
||||||
}
|
|
||||||
req.Header = header
|
|
||||||
|
|
||||||
resp, err := http.DefaultClient.Do(req)
|
|
||||||
if err != nil {
|
|
||||||
return err
|
|
||||||
}
|
|
||||||
if resp.StatusCode != 200 {
|
|
||||||
return xerrors.Errorf("non-200 response: %d", resp.StatusCode)
|
|
||||||
}
|
|
||||||
|
|
||||||
if err := resp.Body.Close(); err != nil {
|
|
||||||
return err
|
|
||||||
}
|
|
||||||
|
|
||||||
// TODO: keep files around for later stages of sealing
|
|
||||||
return w.remove(typ, sectorID)
|
|
||||||
}
|
|
||||||
|
|
||||||
func (w *worker) remove(typ string, sectorID abi.SectorNumber) error {
|
|
||||||
filename := filepath.Join(w.repo, typ, w.sb.SectorName(sectorID))
|
|
||||||
return os.RemoveAll(filename)
|
|
||||||
}
|
|
||||||
|
|
||||||
func (w *worker) fetchSector(sectorID abi.SectorNumber, typ sectorbuilder.WorkerTaskType) error {
|
|
||||||
w.limiter.transferLimit <- struct{}{}
|
|
||||||
defer func() {
|
|
||||||
<-w.limiter.transferLimit
|
|
||||||
}()
|
|
||||||
|
|
||||||
var err error
|
|
||||||
switch typ {
|
|
||||||
case sectorbuilder.WorkerPreCommit:
|
|
||||||
err = w.fetch("staging", sectorID)
|
|
||||||
case sectorbuilder.WorkerCommit:
|
|
||||||
err = w.fetch("sealed", sectorID)
|
|
||||||
if err != nil {
|
|
||||||
return xerrors.Errorf("fetch sealed: %w", err)
|
|
||||||
}
|
|
||||||
err = w.fetch("cache", sectorID)
|
|
||||||
}
|
|
||||||
if err != nil {
|
|
||||||
return xerrors.Errorf("fetch failed: %w", err)
|
|
||||||
}
|
|
||||||
return nil
|
|
||||||
}
|
|
||||||
*/
|
|
||||||
|
@ -7,7 +7,6 @@ import (
|
|||||||
"os"
|
"os"
|
||||||
"strconv"
|
"strconv"
|
||||||
|
|
||||||
"github.com/gorilla/mux"
|
|
||||||
"github.com/ipfs/go-cid"
|
"github.com/ipfs/go-cid"
|
||||||
"golang.org/x/xerrors"
|
"golang.org/x/xerrors"
|
||||||
|
|
||||||
@ -48,122 +47,7 @@ func (sm *StorageMinerAPI) ServeRemote(w http.ResponseWriter, r *http.Request) {
|
|||||||
return
|
return
|
||||||
}
|
}
|
||||||
|
|
||||||
mux := mux.NewRouter()
|
sm.StorageMgr.ServeHTTP(w, r)
|
||||||
|
|
||||||
mux.HandleFunc("/remote/{type}/{id}", sm.remoteGetSector).Methods("GET")
|
|
||||||
mux.HandleFunc("/remote/{type}/{id}", sm.remotePutSector).Methods("PUT")
|
|
||||||
|
|
||||||
log.Infof("SERVEGETREMOTE %s", r.URL)
|
|
||||||
|
|
||||||
mux.ServeHTTP(w, r)
|
|
||||||
}
|
|
||||||
|
|
||||||
func (sm *StorageMinerAPI) remoteGetSector(w http.ResponseWriter, r *http.Request) {
|
|
||||||
panic("todo")
|
|
||||||
/* vars := mux.Vars(r)
|
|
||||||
|
|
||||||
id, err := strconv.ParseUint(vars["id"], 10, 64)
|
|
||||||
if err != nil {
|
|
||||||
log.Error("parsing sector id: ", err)
|
|
||||||
w.WriteHeader(500)
|
|
||||||
return
|
|
||||||
}
|
|
||||||
|
|
||||||
path, err := sm.SectorBuilder.SectorPath(fs.DataType(vars["type"]), abi.SectorNumber(id))
|
|
||||||
if err != nil {
|
|
||||||
log.Error(err)
|
|
||||||
w.WriteHeader(500)
|
|
||||||
return
|
|
||||||
}
|
|
||||||
|
|
||||||
stat, err := os.Stat(string(path))
|
|
||||||
if err != nil {
|
|
||||||
log.Error(err)
|
|
||||||
w.WriteHeader(500)
|
|
||||||
return
|
|
||||||
}
|
|
||||||
|
|
||||||
var rd io.Reader
|
|
||||||
if stat.IsDir() {
|
|
||||||
rd, err = tarutil.TarDirectory(string(path))
|
|
||||||
w.Header().Set("Content-Type", "application/x-tar")
|
|
||||||
} else {
|
|
||||||
rd, err = os.OpenFile(string(path), os.O_RDONLY, 0644)
|
|
||||||
w.Header().Set("Content-Type", "application/octet-stream")
|
|
||||||
}
|
|
||||||
if err != nil {
|
|
||||||
log.Error(err)
|
|
||||||
w.WriteHeader(500)
|
|
||||||
return
|
|
||||||
}
|
|
||||||
|
|
||||||
w.WriteHeader(200)
|
|
||||||
if _, err := io.Copy(w, rd); err != nil {
|
|
||||||
log.Error(err)
|
|
||||||
return
|
|
||||||
}*/
|
|
||||||
}
|
|
||||||
|
|
||||||
func (sm *StorageMinerAPI) remotePutSector(w http.ResponseWriter, r *http.Request) {
|
|
||||||
panic("todo")
|
|
||||||
/* vars := mux.Vars(r)
|
|
||||||
|
|
||||||
id, err := strconv.ParseUint(vars["id"], 10, 64)
|
|
||||||
if err != nil {
|
|
||||||
log.Error("parsing sector id: ", err)
|
|
||||||
w.WriteHeader(500)
|
|
||||||
return
|
|
||||||
}
|
|
||||||
|
|
||||||
// This is going to get better with worker-to-worker transfers
|
|
||||||
|
|
||||||
path, err := sm.SectorBuilder.SectorPath(fs.DataType(vars["type"]), abi.SectorNumber(id))
|
|
||||||
if err != nil {
|
|
||||||
if err != fs.ErrNotFound {
|
|
||||||
log.Error(err)
|
|
||||||
w.WriteHeader(500)
|
|
||||||
return
|
|
||||||
}
|
|
||||||
|
|
||||||
path, err = sm.SectorBuilder.AllocSectorPath(fs.DataType(vars["type"]), abi.SectorNumber(id), true)
|
|
||||||
if err != nil {
|
|
||||||
log.Error(err)
|
|
||||||
w.WriteHeader(500)
|
|
||||||
return
|
|
||||||
}
|
|
||||||
}
|
|
||||||
|
|
||||||
mediatype, _, err := mime.ParseMediaType(r.Header.Get("Content-Type"))
|
|
||||||
if err != nil {
|
|
||||||
log.Error(err)
|
|
||||||
w.WriteHeader(500)
|
|
||||||
return
|
|
||||||
}
|
|
||||||
|
|
||||||
if err := os.RemoveAll(string(path)); err != nil {
|
|
||||||
log.Error(err)
|
|
||||||
w.WriteHeader(500)
|
|
||||||
return
|
|
||||||
}
|
|
||||||
|
|
||||||
switch mediatype {
|
|
||||||
case "application/x-tar":
|
|
||||||
if err := tarutil.ExtractTar(r.Body, string(path)); err != nil {
|
|
||||||
log.Error(err)
|
|
||||||
w.WriteHeader(500)
|
|
||||||
return
|
|
||||||
}
|
|
||||||
default:
|
|
||||||
if err := files.WriteTo(files.NewReaderFile(r.Body), string(path)); err != nil {
|
|
||||||
log.Error(err)
|
|
||||||
w.WriteHeader(500)
|
|
||||||
return
|
|
||||||
}
|
|
||||||
}
|
|
||||||
|
|
||||||
w.WriteHeader(200)
|
|
||||||
|
|
||||||
log.Infof("received %s sector (%s): %d bytes", vars["type"], vars["sname"], r.ContentLength)*/
|
|
||||||
}
|
}
|
||||||
|
|
||||||
/*
|
/*
|
||||||
|
@ -4,13 +4,15 @@ import (
|
|||||||
"context"
|
"context"
|
||||||
"io"
|
"io"
|
||||||
|
|
||||||
storage2 "github.com/filecoin-project/specs-storage/storage"
|
|
||||||
"github.com/ipfs/go-cid"
|
"github.com/ipfs/go-cid"
|
||||||
"golang.org/x/xerrors"
|
"golang.org/x/xerrors"
|
||||||
|
|
||||||
"github.com/filecoin-project/go-address"
|
"github.com/filecoin-project/go-address"
|
||||||
"github.com/filecoin-project/go-sectorbuilder"
|
|
||||||
"github.com/filecoin-project/specs-actors/actors/abi"
|
"github.com/filecoin-project/specs-actors/actors/abi"
|
||||||
|
storage2 "github.com/filecoin-project/specs-storage/storage"
|
||||||
|
|
||||||
|
"github.com/filecoin-project/go-sectorbuilder"
|
||||||
|
"github.com/filecoin-project/lotus/api"
|
||||||
|
|
||||||
"github.com/filecoin-project/lotus/storage/sealmgr"
|
"github.com/filecoin-project/lotus/storage/sealmgr"
|
||||||
)
|
)
|
||||||
@ -100,8 +102,8 @@ func (l *localWorker) TaskTypes(context.Context) (map[sealmgr.TaskType]struct{},
|
|||||||
}, nil
|
}, nil
|
||||||
}
|
}
|
||||||
|
|
||||||
func (l *localWorker) Paths() []Path {
|
func (l *localWorker) Paths(context.Context) ([]api.StoragePath, error) {
|
||||||
return l.storage.local()
|
return l.storage.local(), nil
|
||||||
}
|
}
|
||||||
|
|
||||||
var _ Worker = &localWorker{}
|
var _ Worker = &localWorker{}
|
||||||
|
@ -3,6 +3,7 @@ package advmgr
|
|||||||
import (
|
import (
|
||||||
"context"
|
"context"
|
||||||
"io"
|
"io"
|
||||||
|
"net/http"
|
||||||
|
|
||||||
"github.com/ipfs/go-cid"
|
"github.com/ipfs/go-cid"
|
||||||
logging "github.com/ipfs/go-log/v2"
|
logging "github.com/ipfs/go-log/v2"
|
||||||
@ -11,6 +12,8 @@ import (
|
|||||||
|
|
||||||
"github.com/filecoin-project/go-address"
|
"github.com/filecoin-project/go-address"
|
||||||
"github.com/filecoin-project/go-sectorbuilder"
|
"github.com/filecoin-project/go-sectorbuilder"
|
||||||
|
"github.com/filecoin-project/lotus/api"
|
||||||
|
|
||||||
"github.com/filecoin-project/specs-actors/actors/abi"
|
"github.com/filecoin-project/specs-actors/actors/abi"
|
||||||
storage2 "github.com/filecoin-project/specs-storage/storage"
|
storage2 "github.com/filecoin-project/specs-storage/storage"
|
||||||
|
|
||||||
@ -24,26 +27,11 @@ type SectorIDCounter interface {
|
|||||||
Next() (abi.SectorNumber, error)
|
Next() (abi.SectorNumber, error)
|
||||||
}
|
}
|
||||||
|
|
||||||
type LocalStorage interface {
|
|
||||||
GetStorage() (config.StorageConfig, error)
|
|
||||||
SetStorage(func(*config.StorageConfig)) error
|
|
||||||
}
|
|
||||||
|
|
||||||
type Path struct {
|
|
||||||
ID string
|
|
||||||
Weight uint64
|
|
||||||
|
|
||||||
LocalPath string
|
|
||||||
|
|
||||||
CanSeal bool
|
|
||||||
CanStore bool
|
|
||||||
}
|
|
||||||
|
|
||||||
type Worker interface {
|
type Worker interface {
|
||||||
sectorbuilder.Sealer
|
sectorbuilder.Sealer
|
||||||
|
|
||||||
TaskTypes(context.Context) (map[sealmgr.TaskType]struct{}, error)
|
TaskTypes(context.Context) (map[sealmgr.TaskType]struct{}, error)
|
||||||
Paths() []Path
|
Paths(context.Context) ([]api.StoragePath, error)
|
||||||
}
|
}
|
||||||
|
|
||||||
type Manager struct {
|
type Manager struct {
|
||||||
@ -107,6 +95,10 @@ func (m *Manager) AddLocalStorage(path string) error {
|
|||||||
return nil
|
return nil
|
||||||
}
|
}
|
||||||
|
|
||||||
|
func (m *Manager) ServeHTTP(w http.ResponseWriter, r *http.Request) {
|
||||||
|
m.storage.ServeHTTP(w, r)
|
||||||
|
}
|
||||||
|
|
||||||
func (m *Manager) SectorSize() abi.SectorSize {
|
func (m *Manager) SectorSize() abi.SectorSize {
|
||||||
sz, _ := m.scfg.SealProofType.SectorSize()
|
sz, _ := m.scfg.SealProofType.SectorSize()
|
||||||
return sz
|
return sz
|
||||||
@ -134,16 +126,22 @@ func (m *Manager) getWorkersByPaths(task sealmgr.TaskType, inPaths []config.Stor
|
|||||||
continue
|
continue
|
||||||
}
|
}
|
||||||
|
|
||||||
|
phs, err := worker.Paths(context.TODO())
|
||||||
|
if err != nil {
|
||||||
|
log.Errorf("error getting worker paths: %+v", err)
|
||||||
|
continue
|
||||||
|
}
|
||||||
|
|
||||||
// check if the worker has access to the path we selected
|
// check if the worker has access to the path we selected
|
||||||
var st *config.StorageMeta
|
var st *config.StorageMeta
|
||||||
for _, p := range worker.Paths() {
|
for _, p := range phs {
|
||||||
for _, m := range inPaths {
|
for _, meta := range inPaths {
|
||||||
if p.ID == m.ID {
|
if p.ID == meta.ID {
|
||||||
if st != nil && st.Weight > p.Weight {
|
if st != nil && st.Weight > p.Weight {
|
||||||
continue
|
continue
|
||||||
}
|
}
|
||||||
|
|
||||||
p := m // copy
|
p := meta // copy
|
||||||
st = &p
|
st = &p
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
@ -9,7 +9,6 @@ import (
|
|||||||
"golang.org/x/xerrors"
|
"golang.org/x/xerrors"
|
||||||
|
|
||||||
"github.com/filecoin-project/lotus/api"
|
"github.com/filecoin-project/lotus/api"
|
||||||
"github.com/filecoin-project/lotus/api/apistruct"
|
|
||||||
"github.com/filecoin-project/lotus/api/client"
|
"github.com/filecoin-project/lotus/api/client"
|
||||||
)
|
)
|
||||||
|
|
||||||
@ -18,15 +17,11 @@ type remote struct {
|
|||||||
}
|
}
|
||||||
|
|
||||||
func (r *remote) AddPiece(ctx context.Context, sector abi.SectorNumber, pieceSizes []abi.UnpaddedPieceSize, newPieceSize abi.UnpaddedPieceSize, pieceData storage2.Data) (abi.PieceInfo, error) {
|
func (r *remote) AddPiece(ctx context.Context, sector abi.SectorNumber, pieceSizes []abi.UnpaddedPieceSize, newPieceSize abi.UnpaddedPieceSize, pieceData storage2.Data) (abi.PieceInfo, error) {
|
||||||
panic("implement me")
|
return abi.PieceInfo{},xerrors.New("unsupported")
|
||||||
}
|
|
||||||
|
|
||||||
func (r *remote) Paths() []Path {
|
|
||||||
panic("implement me")
|
|
||||||
}
|
}
|
||||||
|
|
||||||
func ConnectRemote(ctx context.Context, fa api.FullNode, url string) (*remote, error) {
|
func ConnectRemote(ctx context.Context, fa api.FullNode, url string) (*remote, error) {
|
||||||
token, err := fa.AuthNew(ctx, []api.Permission{apistruct.PermAdmin})
|
token, err := fa.AuthNew(ctx, []api.Permission{"admin"})
|
||||||
if err != nil {
|
if err != nil {
|
||||||
return nil, xerrors.Errorf("creating auth token for remote connection: %w", err)
|
return nil, xerrors.Errorf("creating auth token for remote connection: %w", err)
|
||||||
}
|
}
|
||||||
|
@ -3,14 +3,20 @@ package advmgr
|
|||||||
import (
|
import (
|
||||||
"encoding/json"
|
"encoding/json"
|
||||||
"fmt"
|
"fmt"
|
||||||
|
"io"
|
||||||
"io/ioutil"
|
"io/ioutil"
|
||||||
|
"net/http"
|
||||||
"os"
|
"os"
|
||||||
"path/filepath"
|
"path/filepath"
|
||||||
"sync"
|
"sync"
|
||||||
|
|
||||||
|
"github.com/gorilla/mux"
|
||||||
"golang.org/x/xerrors"
|
"golang.org/x/xerrors"
|
||||||
|
|
||||||
"github.com/filecoin-project/go-sectorbuilder"
|
"github.com/filecoin-project/go-sectorbuilder"
|
||||||
|
"github.com/filecoin-project/lotus/api"
|
||||||
|
"github.com/filecoin-project/lotus/lib/tarutil"
|
||||||
|
|
||||||
"github.com/filecoin-project/specs-actors/actors/abi"
|
"github.com/filecoin-project/specs-actors/actors/abi"
|
||||||
|
|
||||||
"github.com/filecoin-project/lotus/node/config"
|
"github.com/filecoin-project/lotus/node/config"
|
||||||
@ -129,6 +135,9 @@ func (st *storage) acquireSector(mid abi.ActorID, id abi.SectorNumber, existing
|
|||||||
if s&fileType == 0 {
|
if s&fileType == 0 {
|
||||||
continue
|
continue
|
||||||
}
|
}
|
||||||
|
if p.local == "" {
|
||||||
|
continue // TODO: fetch
|
||||||
|
}
|
||||||
|
|
||||||
spath := filepath.Join(p.local, fileType.String(), fmt.Sprintf("s-t0%d-%d", mid, id))
|
spath := filepath.Join(p.local, fileType.String(), fmt.Sprintf("s-t0%d-%d", mid, id))
|
||||||
|
|
||||||
@ -239,14 +248,14 @@ func (st *storage) findSector(mid abi.ActorID, sn abi.SectorNumber, typ sectorbu
|
|||||||
return out, nil
|
return out, nil
|
||||||
}
|
}
|
||||||
|
|
||||||
func (st *storage) local() []Path {
|
func (st *storage) local() []api.StoragePath {
|
||||||
var out []Path
|
var out []api.StoragePath
|
||||||
for _, p := range st.paths {
|
for _, p := range st.paths {
|
||||||
if p.local == "" {
|
if p.local == "" {
|
||||||
continue
|
continue
|
||||||
}
|
}
|
||||||
|
|
||||||
out = append(out, Path{
|
out = append(out, api.StoragePath{
|
||||||
ID: p.meta.ID,
|
ID: p.meta.ID,
|
||||||
Weight: p.meta.Weight,
|
Weight: p.meta.Weight,
|
||||||
LocalPath: p.local,
|
LocalPath: p.local,
|
||||||
@ -258,6 +267,93 @@ func (st *storage) local() []Path {
|
|||||||
return out
|
return out
|
||||||
}
|
}
|
||||||
|
|
||||||
|
func (st *storage) ServeHTTP(w http.ResponseWriter, r *http.Request) { // /storage/
|
||||||
|
mux := mux.NewRouter()
|
||||||
|
|
||||||
|
mux.HandleFunc("/{type}/{id}", st.remoteGetSector).Methods("GET")
|
||||||
|
|
||||||
|
log.Infof("SERVEGETREMOTE %s", r.URL)
|
||||||
|
|
||||||
|
mux.ServeHTTP(w, r)
|
||||||
|
}
|
||||||
|
|
||||||
|
|
||||||
|
func (st *storage) remoteGetSector(w http.ResponseWriter, r *http.Request) {
|
||||||
|
vars := mux.Vars(r)
|
||||||
|
|
||||||
|
id, err := parseSectorID(vars["id"])
|
||||||
|
if err != nil {
|
||||||
|
log.Error(err)
|
||||||
|
w.WriteHeader(500)
|
||||||
|
return
|
||||||
|
}
|
||||||
|
|
||||||
|
ft, err := ftFromString(vars["type"])
|
||||||
|
if err != nil {
|
||||||
|
return
|
||||||
|
}
|
||||||
|
paths, done, err := st.acquireSector(id.Miner, id.Number, ft, 0, false)
|
||||||
|
if err != nil {
|
||||||
|
return
|
||||||
|
}
|
||||||
|
defer done()
|
||||||
|
|
||||||
|
var path string
|
||||||
|
switch ft {
|
||||||
|
case sectorbuilder.FTUnsealed:
|
||||||
|
path = paths.Unsealed
|
||||||
|
case sectorbuilder.FTSealed:
|
||||||
|
path = paths.Sealed
|
||||||
|
case sectorbuilder.FTCache:
|
||||||
|
path = paths.Cache
|
||||||
|
}
|
||||||
|
if path == "" {
|
||||||
|
log.Error("acquired path was empty")
|
||||||
|
w.WriteHeader(500)
|
||||||
|
return
|
||||||
|
}
|
||||||
|
|
||||||
|
stat, err := os.Stat(path)
|
||||||
|
if err != nil {
|
||||||
|
log.Error(err)
|
||||||
|
w.WriteHeader(500)
|
||||||
|
return
|
||||||
|
}
|
||||||
|
|
||||||
|
var rd io.Reader
|
||||||
|
if stat.IsDir() {
|
||||||
|
rd, err = tarutil.TarDirectory(path)
|
||||||
|
w.Header().Set("Content-Type", "application/x-tar")
|
||||||
|
} else {
|
||||||
|
rd, err = os.OpenFile(path, os.O_RDONLY, 0644)
|
||||||
|
w.Header().Set("Content-Type", "application/octet-stream")
|
||||||
|
}
|
||||||
|
if err != nil {
|
||||||
|
log.Error(err)
|
||||||
|
w.WriteHeader(500)
|
||||||
|
return
|
||||||
|
}
|
||||||
|
|
||||||
|
w.WriteHeader(200)
|
||||||
|
if _, err := io.Copy(w, rd); err != nil { // TODO: default 32k buf may be too small
|
||||||
|
log.Error(err)
|
||||||
|
return
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
func ftFromString(t string) (sectorbuilder.SectorFileType, error) {
|
||||||
|
switch t {
|
||||||
|
case sectorbuilder.FTUnsealed.String():
|
||||||
|
return sectorbuilder.FTUnsealed, nil
|
||||||
|
case sectorbuilder.FTSealed.String():
|
||||||
|
return sectorbuilder.FTSealed, nil
|
||||||
|
case sectorbuilder.FTCache.String():
|
||||||
|
return sectorbuilder.FTCache, nil
|
||||||
|
default:
|
||||||
|
return 0, xerrors.Errorf("unknown sector file type: '%s'", t)
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
func parseSectorID(baseName string) (abi.SectorID, error) {
|
func parseSectorID(baseName string) (abi.SectorID, error) {
|
||||||
var n abi.SectorNumber
|
var n abi.SectorNumber
|
||||||
var mid abi.ActorID
|
var mid abi.ActorID
|
||||||
|
10
storage/sealmgr/advmgr/storage_local.go
Normal file
10
storage/sealmgr/advmgr/storage_local.go
Normal file
@ -0,0 +1,10 @@
|
|||||||
|
package advmgr
|
||||||
|
|
||||||
|
import (
|
||||||
|
"github.com/filecoin-project/lotus/node/config"
|
||||||
|
)
|
||||||
|
|
||||||
|
type LocalStorage interface {
|
||||||
|
GetStorage() (config.StorageConfig, error)
|
||||||
|
SetStorage(func(*config.StorageConfig)) error
|
||||||
|
}
|
Loading…
Reference in New Issue
Block a user