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

Add "ipfs block rm" command. #2962

Merged
merged 7 commits into from
Aug 18, 2016
Merged

Add "ipfs block rm" command. #2962

merged 7 commits into from
Aug 18, 2016

Conversation

kevina
Copy link
Contributor

@kevina kevina commented Jul 10, 2016

This is a basic implementation for #2914.

It accepts multiple blocks to remove, however that does not provide any performance benifit just yet as it calls pins.IsPinned() for each block, which traverses every recursive pin to check for indirect pins. This operation costs is O(P*N) where P is the number of pinned blocks and N is the number of blocks to be removed. With a little effort this can be brought down to O(P) by checking for multiple pins at once.

Since the pin check is expensive it provides an option to ignore pins. Removing a pinned block will break any command that checks for pins. Right now if this happens recovering from the situation is very difficult. At very least a command should be provided to list any broken or missing pins. An additional optional command can be provided to attempt to repair recursive pins.

TODO:

  • Provide command to check for multiple pins at once

No longer relevant:

  • [] Provide a ipfs pin verify command to list broken or missing pins

Optional and No longer relevant

@kevina kevina added the status/in-progress In progress label Jul 10, 2016
@RichardLitt
Copy link
Member

Nice! Subscribing, for the http-api-spec.

cmds.BoolOption("ignore-pins", "Ignore pins.").Default(false),
},
Run: func(req cmds.Request, res cmds.Response) {
ignorePins, _, err := req.Option("ignore-pins").Bool()
Copy link
Member

Choose a reason for hiding this comment

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

having this option makes me very nervous. Things break rather spectaculary when we have missing blocks that are pinned

Copy link
Contributor Author

@kevina kevina Jul 13, 2016

Choose a reason for hiding this comment

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

I Know. But I see is as necessary, at least until we can get pinning operations to be O(1). Please also see my initial description on this pr and #2963.

@whyrusleeping
Copy link
Member

I'm still not comfortable having the option to ignore pins here, letting a single command have the power to corrupt your repo isnt a very good idea.

@kevina kevina mentioned this pull request Aug 9, 2016
@kevina
Copy link
Contributor Author

kevina commented Aug 10, 2016

@whyrusleeping please have another look. I send the results as a channel and use PostRun now to process the results. I also avoid aborting on a non-fatal error and instead just report that the block can't be deleted and continue on to the next block.

I am okay with removing the option to ignore pins, but I want to fix the pin checks so it is O(p) instead of O(p*n) where p is the number of pinned blocks and n is the number of blocks to be removed.

@whyrusleeping
Copy link
Member

Yeah, if we're removing that option then that all looks pretty good.

@kevina
Copy link
Contributor Author

kevina commented Aug 15, 2016

@whyrusleeping okay, for now I removed the option to ignore pins

If you are happy with this fell free to merge.

@kevina kevina changed the title [WIP] Add "ipfs block rm" command. Add "ipfs block rm" command. Aug 15, 2016
@kevina kevina added need/review Needs a review and removed status/in-progress In progress labels Aug 15, 2016
@kevina kevina force-pushed the kevina/block-rm branch 2 times, most recently from 1f158c6 to b39aff6 Compare August 15, 2016 05:49
License: MIT
Signed-off-by: Kevin Atkinson <[email protected]>
Provide a new method, Pinner.CheckIfPinned(), which will check if
any of the arguments are pinned.  Previously IsPinned would need to be
called once for each block.  The new method will speed up the checking
of multiple pinned blocks from O(p*n) to O(p) (where p is the number
of pinned blocks and n is the number of blocks to be check)

Use the new method in "block rm".

License: MIT
Signed-off-by: Kevin Atkinson <[email protected]>
License: MIT
Signed-off-by: Kevin Atkinson <[email protected]>
@daviddias
Copy link
Member

@whyrusleeping do you need anything else for this PR? Looking forward to have #2914 so that ipfs-inactive/js-ipfs-http-client#305 can be finished with regards to the Block API :)

@whyrusleeping
Copy link
Member

This looks pretty good to me, it sucks that we have to be so hacky with the commands lib PostRun stuff. Maybe we can figure out a better way to restructure that code in the future.

Only thing i'd want to see added here is a test of removing multiple blocks, where a subset of them are pinned.

License: MIT
Signed-off-by: Kevin Atkinson <[email protected]>
@kevina
Copy link
Contributor Author

kevina commented Aug 16, 2016

@whyrusleeping okay I added a test that deleted both pinned and un-pinned and non-existent blocks and made sure that the valid, un-pinned blocks where removed.

@Kubuxu I fixed a bug in the arccache.DeleteBlock() method in bf7c5b3. It seamed a small enough issue that it wasn't worth a separate pull request.

@whyrusleeping
Copy link
Member

@kevina i'm not so sure that was a bug in the arccache. I guess it depends on your perspective, if i call delete on something that doesnt exist, should it ever be a problem that it doesnt exist?

@kevina
Copy link
Contributor Author

kevina commented Aug 17, 2016

@whyrusleeping the cache changes the behavior of the DeleteBlock() method which does return an error if a key was not found, therefore I consider it a bug. The cache itself relies in DeleteBlock() returning an error if a block was not found. Also I would prefer that "block rm" returns an error if a non-existent block is deleted in case I mistyped the key (or more likely I copy and pasted a key but missed a couple of characters.) If this becomes a blocker I can remove the fix and not test for deleting a non-existent block in my test case.

@Kubuxu, your view on this?

…ocks

Add test that removes a combination of pinned, valid, and non-existent
blocks in one command.

License: MIT
Signed-off-by: Kevin Atkinson <[email protected]>
@jbenet
Copy link
Member

jbenet commented Aug 17, 2016

Clarity on what is meant is important:

  • "make it so X is not on my local repo" should be idempotent
  • "check X exists in my local repo, then remove X from my local repo" not
    idempotent

In general, idempotency is a very important property to have. An op like
this should be by default idempotent. You could use a flag to ask it to
signal when a block was not found.

ipfs block rm --error-if-not-present

On Tue, Aug 16, 2016 at 20:49 Kevin Atkinson [email protected]
wrote:

@whyrusleeping https://github.com/whyrusleeping the cache changes the
behavior of the DeleteBlock() method which does return an error if a key
was not found, therefore I consider it a bug. The cache itself relies in
DeleteBlock() returning an error if a block was not found. Also I would
prefer that "block rm" returns an error if a non-existent block is deleted
in case I mistyped the key (or more likely I copy and pasted a key but
missed a couple of characters.) If this becomes a blocker I can remove the
fix and not test for deleting a non-existent block in my test case.

@Kubuxu https://github.com/Kubuxu, your view on this?


You are receiving this because you are subscribed to this thread.
Reply to this email directly, view it on GitHub
#2962 (comment), or mute
the thread
https://github.com/notifications/unsubscribe-auth/AAIcofL46Dx13HsK4gYETd9QPz_n2UdHks5qglqcgaJpZM4JI7L-
.

@kevina
Copy link
Contributor Author

kevina commented Aug 17, 2016

@jbenet the behavior of ipfs block rm is consistent with that of the the rm command. If a block was not found it will complain but still remove any (non-pinned) blocks that are found.

In other words block rm is idempotent, the only difference will be the final status code. All blocks that it can remove will always be removed.

@whyrusleeping
Copy link
Member

Oh, my bad, I read the diff backwards.

On Tue, Aug 16, 2016, 18:49 Kevin Atkinson [email protected] wrote:

@jbenet https://github.com/jbenet the behavior of ipfs block rm is
consistent with that of the the rm command. If a block was not found it
will complain but still remove any (non-pinned) blocks that are found.

In other words block rm is idempotent, the only difference will be the
final status code. All blocks that it can remove will always be removed.


You are receiving this because you were mentioned.

Reply to this email directly, view it on GitHub
#2962 (comment), or mute
the thread
https://github.com/notifications/unsubscribe-auth/ABL4HCF2qmJls6Xyv_X59yL0DDxmSZ-Tks5qgmi7gaJpZM4JI7L-
.

@whyrusleeping
Copy link
Member

@jbenet agreed that idempotency is important, But we need to clearly define the expectations of the datastore interface. Currently, all the datastore implementations will return ErrNotFound when delete is called on a non-existent key. If we want to change that, we need to go through and ensure that every datastore implementation behaves the same way.

@whyrusleeping
Copy link
Member

This LGTM. I'll wait for @Kubuxu to review as well

@jbenet
Copy link
Member

jbenet commented Aug 17, 2016

The datastore is not the ipfs blocks command. The datastore Delete wants
to give you more information.

I guess you could do what rm does and add -f
On Tue, Aug 16, 2016 at 22:18 Jeromy Johnson [email protected]
wrote:

This LGTM. I'll wait for @Kubuxu https://github.com/Kubuxu to review as
well


You are receiving this because you were mentioned.

Reply to this email directly, view it on GitHub
#2962 (comment), or mute
the thread
https://github.com/notifications/unsubscribe-auth/AAIcoQBp9r-MRXWAfNHX-BAWPO4sNpByks5qgm9ZgaJpZM4JI7L-
.

@jbenet
Copy link
Member

jbenet commented Aug 17, 2016

rm -f
On Tue, Aug 16, 2016 at 23:12 Juan Benet [email protected] wrote:

The datastore is not the ipfs blocks command. The datastore Delete wants
to give you more information.

I guess you could do what rm does and add -f
On Tue, Aug 16, 2016 at 22:18 Jeromy Johnson [email protected]
wrote:

This LGTM. I'll wait for @Kubuxu https://github.com/Kubuxu to review
as well


You are receiving this because you were mentioned.

Reply to this email directly, view it on GitHub
#2962 (comment), or mute
the thread
https://github.com/notifications/unsubscribe-auth/AAIcoQBp9r-MRXWAfNHX-BAWPO4sNpByks5qgm9ZgaJpZM4JI7L-
.

@whyrusleeping
Copy link
Member

@jbenet okay, i thought we were having a discussion about the changes made to the Delete method.

License: MIT
Signed-off-by: Kevin Atkinson <[email protected]>
@kevina
Copy link
Contributor Author

kevina commented Aug 17, 2016

@jbenet I added a "-f" option.

I am of the strong opinion that by default "block rm" should report some sort of error when a block is not found. Doing a quick Google "idempotent delete" brought up this stack overflow question: http://stackoverflow.com/questions/4088350/is-rest-delete-really-idempotent. Multiple people state that idempotency is about side effects not the status code, that is "you can send the request more than once without additional changes to the state of the server".

@whyrusleeping
Copy link
Member

Alright, this all LGTM. Thanks a bunch @kevina !

@whyrusleeping whyrusleeping merged commit 10048ce into master Aug 18, 2016
@whyrusleeping whyrusleeping deleted the kevina/block-rm branch August 18, 2016 20:27
@daviddias
Copy link
Member

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

Successfully merging this pull request may close these issues.

5 participants