Skip to content
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

Define GCDatastore/CheckedDatastore interfaces #68

Merged
merged 4 commits into from
Oct 17, 2017

Conversation

magik6k
Copy link
Member

@magik6k magik6k commented Oct 13, 2017

Both are needed for some badger functionality and may be useful for other future datastores.

CheckedDatastore:

GCDatastore:

@ghost ghost assigned magik6k Oct 13, 2017
@ghost ghost added the status/in-progress In progress label Oct 13, 2017
type CheckedDatastore interface {
Datastore

Check() error
Copy link
Member

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

Maybe Scrub()? We also want to support datastores that can do error correction (where an error is returned iff the datastore is unrecoverable).

An open question is how do deal with partial failures. It would nice to be able to recover as much data as possible.

Copy link
Member Author

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

Check would be invoked by ipfs repo fsck, which for now only removes lock files.

Scrub() does make sense (it could be wired up to ipfs repo verify, to keep repo fsck fast). Does putting this into separate interface SGTY (keeping check for stuff like lock-files)?

Copy link
Member

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

Got it. Yes, having a separate interface sounds good.

Just to make sure, I assume Check() will find and fix any errors related to daemon crashes (i.e., it doesn't just blindly remove the lock file)?


Side note: we should get rid of ipfs repo fsck; IPFS should do any recovery necessary on startup automatically.

@whyrusleeping
Copy link
Member

Be careful, adding methods to these interfaces generally means every wrapper datastore has to implement them as well.

@whyrusleeping
Copy link
Member

We will need to find new interesting ways of abusing the type system

@magik6k
Copy link
Member Author

magik6k commented Oct 14, 2017

That's why I made those into separate interfaces - it can only be implemented where it's needed

@whyrusleeping
Copy link
Member

@magik6k But heres the problem, the default construction of the go-ipfs badgerds is a measure datastore wrapping the badger datastore. So the Datastore we have in the repo is of type measureds.Datastore. In order to call the GarbageCollect method on that, we need to either have that method implemented on the measureds, or be able to access its child directly.

This gets even more complicated in cases like the default flatfs datastore setup, with multiple mounts and measure datastore wrappings.

@magik6k
Copy link
Member Author

magik6k commented Oct 14, 2017

I know that, I started wiring it up to these DS-es locally, but I want interfaces defined first

@Stebalien
Copy link
Member

In order to call the GarbageCollect method on that, we need to either have that method implemented on the measureds, or be able to access its child directly.

We can have things like measureds always implement these interfaces and then try to call the appropriate methods on their wrapped types. We can even provide helper functions that do this:

func Scrub(ds *Datastore) error {
    if s, ok := ds.(*ScrubbedDatastore); ok {
        return s.Scrub()
    }
    return nil // error?
}

@Kubuxu
Copy link
Member

Kubuxu commented Oct 16, 2017

If we go this path, we could implement a WrapperDatastore struct that would do all the forwarding (implementing all the interfaces).
Then Wrapping datastores can override selected functions. Example:

type MeasureDatastore  struct {
    WrappingDatastore
    
    a int
}

func (md *MeastureDatastore) Get.... {
    md++
    return md.WrappingDatastore.Get(k)
}

I am not sure it is the best path to move forward. Something better might be capability system. Just putting it out here.

Copy link
Member

@Kubuxu Kubuxu left a comment

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

As I said, I am not 100% about the solution.

(cleaning out my Review queue).

@whyrusleeping
Copy link
Member

@Stebalien

We can have things like measureds always implement these interfaces and then try to call the appropriate methods on their wrapped types.

I'm not saying this is wrong, but it generally just leads to "everybody implements this interface always"

@Stebalien
Copy link
Member

@whyrusleeping

It's more that wrappers that may potentially wrap a datastore implementing that interface should implement the interface. That's why I suggested providing convenience functions for using these interfaces when available.

@whyrusleeping
Copy link
Member

It might make sense to think about a capability system as @Kubuxu mentions, but these interfaces need work soon-ish anyways, so i'm fine deferring some of that until later.

@Stebalien
Copy link
Member

This system should be forwards compatible so LGTM.

@Stebalien Stebalien merged commit 73c601d into master Oct 17, 2017
@ghost ghost removed the status/in-progress In progress label Oct 17, 2017
@Stebalien Stebalien deleted the feat/new-interfaces branch October 17, 2017 00:53
@@ -114,3 +114,24 @@ func (b *syncBatch) Commit() error {
defer b.mds.Unlock()
return b.batch.Commit()
}

func (d *MutexDatastore) Check() error {
Copy link
Member

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

A bit after the fact, but shouldn't these take the lock?

Copy link
Member Author

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

Yeah, they should. Will push a fix in a bit

Sign up for free to join this conversation on GitHub. Already have an account? Sign in to comment
Labels
None yet
Projects
None yet
Development

Successfully merging this pull request may close these issues.

4 participants