-
Notifications
You must be signed in to change notification settings - Fork 59
New issue
Have a question about this project? Sign up for a free GitHub account to open an issue and contact its maintainers and the community.
By clicking “Sign up for GitHub”, you agree to our terms of service and privacy statement. We’ll occasionally send you account related emails.
Already on GitHub? Sign in to your account
Properly Implement Retrieval Lookups Based on CIDs #57
Conversation
seperate block infos to their own table -- mapping links with pieceCIDs
modify markets to use actual payload CIDs instead of treating payload and piece CIDs as equavalent
very simple implementation of storing a map between payload root and pieceCID. to be augmented later with actual block refs
03eb634
to
9211de0
Compare
There was a problem hiding this comment.
Choose a reason for hiding this comment
The reason will be displayed to describe this comment to others. Learn more.
primarily editorial comments and peanut-gallery stuff
if err := ps.store.Get(newKey(pieceCID)).Get(&out); err != nil { | ||
return PieceInfo{}, err | ||
func (ps *pieceStore) ensurePieceInfo(pieceCID []byte) error { | ||
has, err := ps.pieces.Has(newKey(pieceCID)) |
There was a problem hiding this comment.
Choose a reason for hiding this comment
The reason will be displayed to describe this comment to others. Learn more.
Maybe call it canHasPieceInfo /jk
err := ps.AddDealForPiece(pieceCid, dealInfo) | ||
assert.NoError(t, err) | ||
|
||
pi, err := ps.GetPieceInfo(pieceCid) |
There was a problem hiding this comment.
Choose a reason for hiding this comment
The reason will be displayed to describe this comment to others. Learn more.
nit: I should think you could skip the error/value checking on the first try since it's tested above.
There was a problem hiding this comment.
Choose a reason for hiding this comment
The reason will be displayed to describe this comment to others. Learn more.
I just follow past of least resistance to get no lint-stage errors
@@ -92,3 +87,22 @@ func (lu *loaderWithUnsealing) attemptUnseal() error { | |||
|
|||
return nil | |||
} | |||
|
|||
func (lu *loaderWithUnsealing) firstSuccessfulUnseal(cidInfo piecestore.CIDInfo) (io.ReadCloser, error) { |
There was a problem hiding this comment.
Choose a reason for hiding this comment
The reason will be displayed to describe this comment to others. Learn more.
I'm a little fuzzy on this: If it's already unsealed do you expect the unsealer func not to return an error?
There was a problem hiding this comment.
Choose a reason for hiding this comment
The reason will be displayed to describe this comment to others. Learn more.
so the logic changed a bit here. theoretically since we're basing our queries on payload CIDs, I guess it's possible that a query could span multiple pieces now (if a piece was a partial but not complete DAG -- something we intend to support I believe).
The point of this function is: for a given Cid, find the first piece that it's contained in that we can successfully unseal.
since we unseal and read the whole piece, in theory this function should not get called unless the query we make somehow crosses a piece boundary, which again, I think is possible.
If unsealing fails completely the first time, it's probably alright cause the loader calling code will immediately error and stop the retrieval deal.
@@ -82,12 +82,22 @@ func requireSetupTestClientAndProvider(bgCtx context.Context, t *testing.T, payC | |||
providerNode := testnodes.NewTestRetrievalProviderNode() | |||
pieceStore := tut.NewTestPieceStore() | |||
expectedCIDs := tut.GenerateCids(3) | |||
missingPiece := tut.GenerateCids(1)[0] | |||
expectedPieces := [][]byte{[]byte("applesuace"), []byte("jam"), []byte("apricot")} |
There was a problem hiding this comment.
Choose a reason for hiding this comment
The reason will be displayed to describe this comment to others. Learn more.
I don't know how you resisted using "pork chops" after "applesauce"
sectorID, offset, length, err := p.spn.LocatePieceForDealWithinSector(ctx, deal.DealID) | ||
if err != nil { | ||
return nil, err | ||
} | ||
// TODO: Record actual block locations for all CIDs in piece by improving car writing |
There was a problem hiding this comment.
Choose a reason for hiding this comment
The reason will be displayed to describe this comment to others. Learn more.
SHould this be captured in an issue?
There was a problem hiding this comment.
Choose a reason for hiding this comment
The reason will be displayed to describe this comment to others. Learn more.
yes, it will be soon, that's the intent.
Codecov Report
@@ Coverage Diff @@
## master #57 +/- ##
==========================================
+ Coverage 34.12% 34.62% +0.51%
==========================================
Files 36 36
Lines 2615 2713 +98
==========================================
+ Hits 892 939 +47
- Misses 1588 1617 +29
- Partials 135 157 +22
Continue to review full report at Codecov.
|
There was a problem hiding this comment.
Choose a reason for hiding this comment
The reason will be displayed to describe this comment to others. Learn more.
Looks good so far.
piecestore/piecestore.go
Outdated
} | ||
} | ||
|
||
type pieceStore struct { | ||
store *statestore.StateStore | ||
pieces *statestore.StateStore | ||
cidInfos *statestore.StateStore | ||
} | ||
|
||
func (ps *pieceStore) AddDealForPiece(pieceCID []byte, dealInfo DealInfo) error { | ||
// Do we need to de-dupe or anything here? |
There was a problem hiding this comment.
Choose a reason for hiding this comment
The reason will be displayed to describe this comment to others. Learn more.
Guess we can remove this comment now.
There was a problem hiding this comment.
Choose a reason for hiding this comment
The reason will be displayed to describe this comment to others. Learn more.
ok!
sectorID, offset, length, err := p.spn.LocatePieceForDealWithinSector(ctx, deal.DealID) | ||
if err != nil { | ||
return nil, err | ||
} | ||
// TODO: Record actual block locations for all CIDs in piece by improving car writing | ||
err = p.pieceStore.AddPieceBlockLocations(deal.Proposal.PieceRef, map[cid.Cid]piecestore.BlockLocation{ | ||
deal.Ref: {}, |
There was a problem hiding this comment.
Choose a reason for hiding this comment
The reason will be displayed to describe this comment to others. Learn more.
What is needed to store the root CID location here?
There was a problem hiding this comment.
Choose a reason for hiding this comment
The reason will be displayed to describe this comment to others. Learn more.
even for the root, we need to figure out where it sits within the CAR file, so it will be addressed at the same time we address the todo above
The idea is we can store an index to arbitrary blocks in the IPLD graph of a deal payload, because a CAR file is just blocks that are concatenated together? |
@ingar -- basically yes -- when we write the car, we can basically record for any CID:
And theoretically we might start partial unsealling even pieces based on that, except that requires unsealing to be super fast which... I'm not sure where things are at with that. |
Goals
Allow Retrieval deals to work with actual Payload CIDs
Implementation
-- add a second mapping to the PieceStore that translates from a CID to pieces its a part of
-- support unsealling pieces from CIDs as needed (theoretically a dag could span multiple pieces in the future where pieces are not whole dags -- not super important though)
-- add very preliminary writes of CID -> Piece mapping on storage provider side
--- IMPORTANT: Not included is mapping any CIDs in the IPLD graph other than the root to Piece, or recording where in the piece blocks actually live. This can definitely be done by recording this information as we write the CAR file. This is definitely temporary implementation meant to get us to working retrieval by payload CID fast, with allowing retrievals based off of CIDs deeper in the dag later.