2024-02-11 17:50:37 +00:00
|
|
|
package hapi
|
|
|
|
|
|
|
|
import (
|
2024-04-11 16:30:53 +00:00
|
|
|
"context"
|
2024-02-11 17:50:37 +00:00
|
|
|
"net/http"
|
|
|
|
"time"
|
|
|
|
|
|
|
|
"golang.org/x/xerrors"
|
|
|
|
|
|
|
|
"github.com/filecoin-project/go-address"
|
|
|
|
"github.com/filecoin-project/go-bitfield"
|
|
|
|
|
2024-04-11 16:30:53 +00:00
|
|
|
"github.com/filecoin-project/lotus/chain/actors/adt"
|
2024-02-11 17:50:37 +00:00
|
|
|
"github.com/filecoin-project/lotus/chain/actors/builtin/miner"
|
|
|
|
"github.com/filecoin-project/lotus/chain/types"
|
|
|
|
"github.com/filecoin-project/lotus/lib/must"
|
|
|
|
)
|
|
|
|
|
2024-04-11 16:30:53 +00:00
|
|
|
type PipelineTask struct {
|
|
|
|
SpID int64 `db:"sp_id"`
|
|
|
|
SectorNumber int64 `db:"sector_number"`
|
2024-02-20 13:08:09 +00:00
|
|
|
|
2024-04-11 16:30:53 +00:00
|
|
|
CreateTime time.Time `db:"create_time"`
|
2024-02-11 17:50:37 +00:00
|
|
|
|
2024-04-11 16:30:53 +00:00
|
|
|
TaskSDR *int64 `db:"task_id_sdr"`
|
|
|
|
AfterSDR bool `db:"after_sdr"`
|
2024-02-11 17:50:37 +00:00
|
|
|
|
2024-04-11 16:30:53 +00:00
|
|
|
TaskTreeD *int64 `db:"task_id_tree_d"`
|
|
|
|
AfterTreeD bool `db:"after_tree_d"`
|
2024-02-11 17:50:37 +00:00
|
|
|
|
2024-04-11 16:30:53 +00:00
|
|
|
TaskTreeC *int64 `db:"task_id_tree_c"`
|
|
|
|
AfterTreeC bool `db:"after_tree_c"`
|
2024-02-11 17:50:37 +00:00
|
|
|
|
2024-04-11 16:30:53 +00:00
|
|
|
TaskTreeR *int64 `db:"task_id_tree_r"`
|
|
|
|
AfterTreeR bool `db:"after_tree_r"`
|
2024-02-11 17:50:37 +00:00
|
|
|
|
2024-04-11 16:30:53 +00:00
|
|
|
TaskPrecommitMsg *int64 `db:"task_id_precommit_msg"`
|
|
|
|
AfterPrecommitMsg bool `db:"after_precommit_msg"`
|
2024-02-11 17:50:37 +00:00
|
|
|
|
2024-04-11 16:30:53 +00:00
|
|
|
AfterPrecommitMsgSuccess bool `db:"after_precommit_msg_success"`
|
|
|
|
SeedEpoch *int64 `db:"seed_epoch"`
|
2024-02-11 17:50:37 +00:00
|
|
|
|
2024-04-11 16:30:53 +00:00
|
|
|
TaskPoRep *int64 `db:"task_id_porep"`
|
|
|
|
PoRepProof []byte `db:"porep_proof"`
|
|
|
|
AfterPoRep bool `db:"after_porep"`
|
2024-02-11 17:50:37 +00:00
|
|
|
|
2024-04-11 16:30:53 +00:00
|
|
|
TaskFinalize *int64 `db:"task_id_finalize"`
|
|
|
|
AfterFinalize bool `db:"after_finalize"`
|
2024-02-11 17:50:37 +00:00
|
|
|
|
2024-04-11 16:30:53 +00:00
|
|
|
TaskMoveStorage *int64 `db:"task_id_move_storage"`
|
|
|
|
AfterMoveStorage bool `db:"after_move_storage"`
|
2024-02-11 17:50:37 +00:00
|
|
|
|
2024-04-11 16:30:53 +00:00
|
|
|
TaskCommitMsg *int64 `db:"task_id_commit_msg"`
|
|
|
|
AfterCommitMsg bool `db:"after_commit_msg"`
|
2024-02-11 17:50:37 +00:00
|
|
|
|
2024-04-11 16:30:53 +00:00
|
|
|
AfterCommitMsgSuccess bool `db:"after_commit_msg_success"`
|
2024-02-11 17:50:37 +00:00
|
|
|
|
2024-04-11 16:30:53 +00:00
|
|
|
Failed bool `db:"failed"`
|
|
|
|
FailedReason string `db:"failed_reason"`
|
|
|
|
}
|
2024-02-11 17:50:37 +00:00
|
|
|
|
2024-04-11 16:30:53 +00:00
|
|
|
type sectorListEntry struct {
|
|
|
|
PipelineTask
|
2024-02-11 17:50:37 +00:00
|
|
|
|
2024-04-11 16:30:53 +00:00
|
|
|
Address address.Address
|
|
|
|
CreateTime string
|
|
|
|
AfterSeed bool
|
|
|
|
|
|
|
|
ChainAlloc, ChainSector, ChainActive, ChainUnproven, ChainFaulty bool
|
|
|
|
}
|
|
|
|
|
|
|
|
type minerBitfields struct {
|
|
|
|
alloc, sectorSet, active, unproven, faulty bitfield.BitField
|
|
|
|
}
|
|
|
|
|
|
|
|
func (a *app) pipelinePorepSectors(w http.ResponseWriter, r *http.Request) {
|
|
|
|
ctx := r.Context()
|
2024-02-11 17:50:37 +00:00
|
|
|
|
|
|
|
var tasks []PipelineTask
|
|
|
|
|
|
|
|
err := a.db.Select(ctx, &tasks, `SELECT
|
|
|
|
sp_id, sector_number,
|
|
|
|
create_time,
|
|
|
|
task_id_sdr, after_sdr,
|
|
|
|
task_id_tree_d, after_tree_d,
|
|
|
|
task_id_tree_c, after_tree_c,
|
|
|
|
task_id_tree_r, after_tree_r,
|
|
|
|
task_id_precommit_msg, after_precommit_msg,
|
|
|
|
after_precommit_msg_success, seed_epoch,
|
|
|
|
task_id_porep, porep_proof, after_porep,
|
|
|
|
task_id_finalize, after_finalize,
|
|
|
|
task_id_move_storage, after_move_storage,
|
|
|
|
task_id_commit_msg, after_commit_msg,
|
|
|
|
after_commit_msg_success,
|
|
|
|
failed, failed_reason
|
|
|
|
FROM sectors_sdr_pipeline order by sp_id, sector_number`) // todo where constrain list
|
|
|
|
if err != nil {
|
|
|
|
http.Error(w, xerrors.Errorf("failed to fetch pipeline tasks: %w", err).Error(), http.StatusInternalServerError)
|
|
|
|
return
|
|
|
|
}
|
|
|
|
|
|
|
|
head, err := a.workingApi.ChainHead(ctx)
|
|
|
|
if err != nil {
|
|
|
|
http.Error(w, xerrors.Errorf("failed to fetch chain head: %w", err).Error(), http.StatusInternalServerError)
|
|
|
|
return
|
|
|
|
}
|
|
|
|
epoch := head.Height()
|
|
|
|
|
|
|
|
minerBitfieldCache := map[address.Address]minerBitfields{}
|
|
|
|
|
|
|
|
sectorList := make([]sectorListEntry, 0, len(tasks))
|
|
|
|
for _, task := range tasks {
|
|
|
|
task := task
|
|
|
|
|
|
|
|
task.CreateTime = task.CreateTime.Local()
|
|
|
|
|
|
|
|
addr, err := address.NewIDAddress(uint64(task.SpID))
|
|
|
|
if err != nil {
|
|
|
|
http.Error(w, xerrors.Errorf("failed to create actor address: %w", err).Error(), http.StatusInternalServerError)
|
|
|
|
return
|
|
|
|
}
|
|
|
|
|
|
|
|
mbf, ok := minerBitfieldCache[addr]
|
|
|
|
if !ok {
|
2024-05-20 07:56:46 +00:00
|
|
|
mbf, err = a.getMinerBitfields(ctx, addr, a.stor)
|
2024-02-11 17:50:37 +00:00
|
|
|
if err != nil {
|
2024-04-11 16:30:53 +00:00
|
|
|
http.Error(w, xerrors.Errorf("failed to load miner bitfields: %w", err).Error(), http.StatusInternalServerError)
|
2024-02-11 17:50:37 +00:00
|
|
|
return
|
|
|
|
}
|
|
|
|
minerBitfieldCache[addr] = mbf
|
|
|
|
}
|
|
|
|
|
|
|
|
afterSeed := task.SeedEpoch != nil && *task.SeedEpoch <= int64(epoch)
|
|
|
|
|
|
|
|
sectorList = append(sectorList, sectorListEntry{
|
|
|
|
PipelineTask: task,
|
|
|
|
Address: addr,
|
|
|
|
CreateTime: task.CreateTime.Format(time.DateTime),
|
|
|
|
AfterSeed: afterSeed,
|
|
|
|
|
|
|
|
ChainAlloc: must.One(mbf.alloc.IsSet(uint64(task.SectorNumber))),
|
|
|
|
ChainSector: must.One(mbf.sectorSet.IsSet(uint64(task.SectorNumber))),
|
|
|
|
ChainActive: must.One(mbf.active.IsSet(uint64(task.SectorNumber))),
|
|
|
|
ChainUnproven: must.One(mbf.unproven.IsSet(uint64(task.SectorNumber))),
|
|
|
|
ChainFaulty: must.One(mbf.faulty.IsSet(uint64(task.SectorNumber))),
|
|
|
|
})
|
|
|
|
}
|
|
|
|
|
|
|
|
a.executeTemplate(w, "pipeline_porep_sectors", sectorList)
|
|
|
|
}
|
2024-04-11 16:30:53 +00:00
|
|
|
|
|
|
|
func (a *app) getMinerBitfields(ctx context.Context, addr address.Address, stor adt.Store) (minerBitfields, error) {
|
|
|
|
act, err := a.workingApi.StateGetActor(ctx, addr, types.EmptyTSK)
|
|
|
|
if err != nil {
|
|
|
|
return minerBitfields{}, xerrors.Errorf("failed to load actor: %w", err)
|
|
|
|
}
|
|
|
|
|
|
|
|
mas, err := miner.Load(stor, act)
|
|
|
|
if err != nil {
|
|
|
|
return minerBitfields{}, xerrors.Errorf("failed to load miner actor: %w", err)
|
|
|
|
}
|
|
|
|
|
|
|
|
activeSectors, err := miner.AllPartSectors(mas, miner.Partition.ActiveSectors)
|
|
|
|
if err != nil {
|
|
|
|
return minerBitfields{}, xerrors.Errorf("failed to load active sectors: %w", err)
|
|
|
|
}
|
|
|
|
|
|
|
|
allSectors, err := miner.AllPartSectors(mas, miner.Partition.AllSectors)
|
|
|
|
if err != nil {
|
|
|
|
return minerBitfields{}, xerrors.Errorf("failed to load all sectors: %w", err)
|
|
|
|
}
|
|
|
|
|
|
|
|
unproved, err := miner.AllPartSectors(mas, miner.Partition.UnprovenSectors)
|
|
|
|
if err != nil {
|
|
|
|
return minerBitfields{}, xerrors.Errorf("failed to load unproven sectors: %w", err)
|
|
|
|
}
|
|
|
|
|
|
|
|
faulty, err := miner.AllPartSectors(mas, miner.Partition.FaultySectors)
|
|
|
|
if err != nil {
|
|
|
|
return minerBitfields{}, xerrors.Errorf("failed to load faulty sectors: %w", err)
|
|
|
|
}
|
|
|
|
|
|
|
|
alloc, err := mas.GetAllocatedSectors()
|
|
|
|
if err != nil {
|
|
|
|
return minerBitfields{}, xerrors.Errorf("failed to load allocated sectors: %w", err)
|
|
|
|
}
|
|
|
|
|
|
|
|
return minerBitfields{
|
|
|
|
alloc: *alloc,
|
|
|
|
sectorSet: allSectors,
|
|
|
|
active: activeSectors,
|
|
|
|
unproven: unproved,
|
|
|
|
faulty: faulty,
|
|
|
|
}, nil
|
|
|
|
}
|