-
-
Notifications
You must be signed in to change notification settings - Fork 3k
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
Add DAGService.GetLinks() method and use it in the GC and elsewhere. #3255
Conversation
Part of #2634. |
439da7c
to
0c0959a
Compare
It doesnt appear that the linkservice interface has anything that implements it, and doesnt appear to be used anywhere |
Right. It doesn't have a use yet outside of the filestore. This commit has an implementation 5a73226. |
@whyrusleeping, if #2634 is going to get merged within a reasonable amount of time, I am okay with this P.R. not getting merged at the same time as #2634. I mainly separated it out for easier reviewing. |
@kevina I think that we should change the linkservice interface so that the existing dagservice implements it. That way any thing that just needs a link service can still have the dag service passed to it. And any place that needs both should just have the dagservice passed in. Then, for the filestore, we can make a small wrapper around the current dagservice code that overrides the GetLinks method to use the filestore backing instead. That way, it makes it easy for us to do other things later, like plug in a graph database to help resolve links. |
So what i'm getting at here, is that we want the linkservice and the dagservice to ideally be exposed via the same object. Where the linkservice interface is just a limited subset of the dagservices interface. With them separate, a few things start to feel weird. I would never want to call So for the purpose of this PR, we should just be adding the linkservice interface with type FancyDagServiceWithLinkMagic struct {
DAGService
linkStuff *linkResolver
}
func (a *FancyDagServiceWithLinkMagic) GetLinks(....) (Link, error) {
return a.linkStuff.GetLinks(...)
} And upon node construction, use that object as the nodes |
@whyrusleeping @Kubuxu I just pushed a commit that implemented what we seamed to agree on over IRC. |
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 still not sold on the GetOffline
thing. I think that its probably okay to just expect the user to pass the right thing in. I get the appeal of having the type system check that for us, but i think it might be cluttering the interfaces a bit too much.
cc @Kubuxu @diasdavid @jbenet for their thoughts as well
return node.Links, nil | ||
} | ||
|
||
func (n *dagService) GetOfflineLinkService() LinkService { |
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 think this can be moved to the main DAGService
interface. There are many situations where we would want to use this to get an offline dagservice.
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.
Look at the return type.
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.
Right, but the actual implementation is returning an offline DAGService, which is something that we would want to have available.
I'm thinking that when we need an offline linkservice, we could call dag.GetOffline()
(which would return a DAGService
) and then simply pass that into the function requiring the offline linkservice.
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 did it this way to enforce type safety. Otherwise we could be passed a LinkService and get a DAGService. If you really don't like that I can change it.
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.
Type safety is good, lets move forward with this
@@ -366,19 +393,19 @@ func legacyCidFromLink(lnk *Link) *cid.Cid { | |||
// EnumerateChildren will walk the dag below the given root node and add all | |||
// unseen children to the passed in set. | |||
// TODO: parallelize to avoid disk latency perf hits? | |||
func EnumerateChildren(ctx context.Context, ds DAGService, root *Node, visit func(*cid.Cid) bool, bestEffort bool) error { | |||
for _, lnk := range root.Links { | |||
func EnumerateChildren(ctx context.Context, ds LinkService, links []*Link, visit func(*cid.Cid) bool, bestEffort bool) 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 would prefer this just take a since *cid.Cid
as its input instead of an array of links. Makes it easier to call in general.
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.
Okay, I will look into it.
unlocker := bs.GCLock() | ||
|
||
bsrv := bserv.New(bs, offline.Exchange(bs)) | ||
ds := dag.NewDAGService(bsrv) | ||
ls = ls.GetOfflineLinkService() |
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.
Ah, i see why this was on the LinkService
and not the DAGService
. Hrm... thats tricky.
if err != nil { | ||
return err | ||
} | ||
|
||
// EnumerateChildren recursively walks the dag and adds the keys to the given set | ||
err = dag.EnumerateChildren(ctx, ds, nd, func(c *cid.Cid) bool { | ||
// EnumerateChildren recursively walks the dag and adls the keys to the given set |
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.
Typo?
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, will fix the comment.
@@ -521,19 +521,19 @@ func (p *pinner) PinWithMode(c *cid.Cid, mode PinMode) { | |||
} | |||
} | |||
|
|||
func hasChild(ds mdag.DAGService, root *mdag.Node, child key.Key) (bool, error) { | |||
for _, lnk := range root.Links { | |||
func hasChild(ds mdag.LinkService, links []*mdag.Link, child key.Key) (bool, 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.
Should accept a *cid.Cid
instead of []*mdag.Link
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.
Okay, will look into it.
723a743
to
b315144
Compare
@@ -417,3 +417,7 @@ func (bs *Bitswap) GetWantlist() []key.Key { | |||
} | |||
return out | |||
} | |||
|
|||
func (bs *Bitswap) IsOnline() bool { |
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.
It doesnt look like we use this anywhere. Am i missing something or is this just dead code from a different approach?
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.
It is used. I added a IsOnline()
method to exchange to be able to tell if the exchange is online or not.
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.
Ah, yeah. I missed it on my previous pass through
Alright, I think this looks good to me. @Kubuxu wanna give it a good look over? |
Reporter metrics.Reporter | ||
Discovery discovery.Service | ||
FilesRoot *mfs.Root | ||
Peerstore pstore.Peerstore // storage for other Peer instances |
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.
Could you try an undo these changes? its just noise on the diff
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. I was just about to re-base to clean up this diff noise. 😄
2697850
to
f0e5138
Compare
This method will use the (also new) LinkService if it is available to retrieving just the links for a MerkleDAG without necessary having to retrieve the underlying block. For now the main benefit is that the pinner will not break when a block becomes invalid due to a change in the backing file. This is possible because the metadata for a block (that includes the Links) is stored separately and thus always available even if the backing file changes. License: MIT Signed-off-by: Kevin Atkinson <k@kevina.org>
e491d52
to
3899194
Compare
Instead make LinkService a part of DAGService. The LinkService is now simply an interface that DAGService implements. Also provide a GetOfflineLinkService() method that the GC uses to get an offline instance. License: MIT Signed-off-by: Kevin Atkinson <k@kevina.org>
…g.Link Author: Kevin Atkinson <k@kevina.org> Fix EnumerateChildren & hasChild to take a *cid.Cid instead of []*mdag.Link Author: Jeromy Johnson <why@ipfs.io> make FetchGraph use a cid pin: fix TestPinRecursiveFail License: MIT Signed-off-by: Jeromy <why@ipfs.io> License: MIT Signed-off-by: Kevin Atkinson <k@kevina.org>
baad64b
to
721df36
Compare
Just rebased on master and assuming the tests pass this should be good to go. @Kubuxu what do you think? |
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.
LGTM
This method will use the (also new) LinkService if it is available to
retrieving just the links for a MerkleDAG without necessary having to
retrieve the underlying block.
For now the main benefit is that the pinner will not break when a block
becomes invalid due to a change in the backing file. This is possible
because the metadata for a block (that includes the Links) is stored
separately and thus always available even if the backing file changes.
For context (and test cases) please see the original commits: 5a73226 8b396fd