2020-09-14 07:44:55 +00:00
|
|
|
package sectorstorage
|
|
|
|
|
|
|
|
import (
|
2020-09-22 22:26:07 +00:00
|
|
|
"fmt"
|
|
|
|
"io"
|
|
|
|
|
2020-09-14 07:44:55 +00:00
|
|
|
"github.com/filecoin-project/go-statestore"
|
2020-09-22 22:26:07 +00:00
|
|
|
cbg "github.com/whyrusleeping/cbor-gen"
|
|
|
|
"golang.org/x/xerrors"
|
2020-09-14 07:44:55 +00:00
|
|
|
|
|
|
|
"github.com/filecoin-project/lotus/extern/sector-storage/storiface"
|
|
|
|
)
|
|
|
|
|
2020-09-16 15:08:05 +00:00
|
|
|
type workerCallTracker struct {
|
2020-09-14 07:44:55 +00:00
|
|
|
st *statestore.StateStore // by CallID
|
|
|
|
}
|
|
|
|
|
|
|
|
type CallState uint64
|
|
|
|
|
|
|
|
const (
|
|
|
|
CallStarted CallState = iota
|
|
|
|
CallDone
|
|
|
|
// returned -> remove
|
|
|
|
)
|
|
|
|
|
|
|
|
type Call struct {
|
2020-09-21 22:52:33 +00:00
|
|
|
ID storiface.CallID
|
|
|
|
RetType ReturnType
|
|
|
|
|
2020-09-14 07:44:55 +00:00
|
|
|
State CallState
|
|
|
|
|
2020-09-22 22:26:07 +00:00
|
|
|
Result *ManyBytes // json bytes
|
2020-09-14 07:44:55 +00:00
|
|
|
}
|
|
|
|
|
2020-09-21 22:52:33 +00:00
|
|
|
func (wt *workerCallTracker) onStart(ci storiface.CallID, rt ReturnType) error {
|
2020-09-14 07:44:55 +00:00
|
|
|
return wt.st.Begin(ci, &Call{
|
2020-09-21 23:00:17 +00:00
|
|
|
ID: ci,
|
|
|
|
RetType: rt,
|
|
|
|
State: CallStarted,
|
2020-09-14 07:44:55 +00:00
|
|
|
})
|
|
|
|
}
|
|
|
|
|
2020-09-16 15:08:05 +00:00
|
|
|
func (wt *workerCallTracker) onDone(ci storiface.CallID, ret []byte) error {
|
2020-09-14 07:44:55 +00:00
|
|
|
st := wt.st.Get(ci)
|
|
|
|
return st.Mutate(func(cs *Call) error {
|
|
|
|
cs.State = CallDone
|
2020-09-22 22:26:07 +00:00
|
|
|
cs.Result = &ManyBytes{ret}
|
2020-09-14 07:44:55 +00:00
|
|
|
return nil
|
|
|
|
})
|
|
|
|
}
|
|
|
|
|
2020-09-16 15:08:05 +00:00
|
|
|
func (wt *workerCallTracker) onReturned(ci storiface.CallID) error {
|
2020-09-14 07:44:55 +00:00
|
|
|
st := wt.st.Get(ci)
|
|
|
|
return st.End()
|
|
|
|
}
|
2020-09-21 22:52:33 +00:00
|
|
|
|
|
|
|
func (wt *workerCallTracker) unfinished() ([]Call, error) {
|
|
|
|
var out []Call
|
|
|
|
return out, wt.st.List(&out)
|
|
|
|
}
|
2020-09-22 22:26:07 +00:00
|
|
|
|
|
|
|
// Ideally this would be a tag on the struct field telling cbor-gen to enforce higher max-len
|
|
|
|
type ManyBytes struct {
|
|
|
|
b []byte
|
|
|
|
}
|
|
|
|
|
|
|
|
const many = 100 << 20
|
|
|
|
|
|
|
|
func (t *ManyBytes) MarshalCBOR(w io.Writer) error {
|
|
|
|
if t == nil {
|
|
|
|
t = &ManyBytes{}
|
|
|
|
}
|
|
|
|
|
|
|
|
if len(t.b) > many {
|
|
|
|
return xerrors.Errorf("byte array in field t.Result was too long")
|
|
|
|
}
|
|
|
|
|
|
|
|
scratch := make([]byte, 9)
|
|
|
|
|
|
|
|
if err := cbg.WriteMajorTypeHeaderBuf(scratch, w, cbg.MajByteString, uint64(len(t.b))); err != nil {
|
|
|
|
return err
|
|
|
|
}
|
|
|
|
|
|
|
|
if _, err := w.Write(t.b[:]); err != nil {
|
|
|
|
return err
|
|
|
|
}
|
|
|
|
return nil
|
|
|
|
}
|
|
|
|
|
|
|
|
func (t *ManyBytes) UnmarshalCBOR(r io.Reader) error {
|
|
|
|
*t = ManyBytes{}
|
|
|
|
|
|
|
|
br := cbg.GetPeeker(r)
|
|
|
|
scratch := make([]byte, 9)
|
|
|
|
|
|
|
|
maj, extra, err := cbg.CborReadHeaderBuf(br, scratch)
|
|
|
|
if err != nil {
|
|
|
|
return err
|
|
|
|
}
|
|
|
|
|
|
|
|
if extra > many {
|
|
|
|
return fmt.Errorf("byte array too large (%d)", extra)
|
|
|
|
}
|
|
|
|
if maj != cbg.MajByteString {
|
|
|
|
return fmt.Errorf("expected byte array")
|
|
|
|
}
|
|
|
|
|
|
|
|
if extra > 0 {
|
|
|
|
t.b = make([]uint8, extra)
|
|
|
|
}
|
|
|
|
|
|
|
|
if _, err := io.ReadFull(br, t.b[:]); err != nil {
|
|
|
|
return err
|
|
|
|
}
|
|
|
|
|
|
|
|
return nil
|
|
|
|
}
|