@cryptotaxi247 / kubo / commits / 5901e57df

"block rm": move core functionally into blockstore_util package

Note: this code can not go in the "blockstore" package due to a circular dependency with the "pin" package. License: MIT Signed-off-by: Kevin Atkinson <k@kevina.org>

Kevin Atkinson committed Sep 14, 2016 at 18:45 UTC 5901e57dfc65be3c3e10fc28a4c3118a9cc25091
2 files changed +113 -83
blocks/blockstore/util/remove.go new
+100
@@ -0,0 +1,100 @@
1 +package blockstore_util
2 +
3 +import (
4 + "fmt"
5 + "io"
6 +
7 + bs "github.com/ipfs/go-ipfs/blocks/blockstore"
8 + "github.com/ipfs/go-ipfs/pin"
9 + ds "gx/ipfs/QmbzuUusHqaLLoNTDEVLcSF6vZDHZDLPC7p4bztRvvkXxU/go-datastore"
10 + key "gx/ipfs/Qmce4Y4zg3sYr7xKM5UueS67vhNni6EeWgCRnb7MbLJMew/go-key"
11 + cid "gx/ipfs/QmfSc2xehWmWLnwwYR91Y8QF4xdASypTFVknutoKQS3GHp/go-cid"
12 +)
13 +
14 +type RemovedBlock struct {
15 + Hash string `json:",omitempty"`
16 + Error string `json:",omitempty"`
17 +}
18 +
19 +type RmBlocksOpts struct {
20 + Prefix string
21 + Quiet bool
22 + Force bool
23 +}
24 +
25 +func RmBlocks(blocks bs.GCBlockstore, pins pin.Pinner, out chan<- interface{}, cids []*cid.Cid, opts RmBlocksOpts) error {
26 + go func() {
27 + defer close(out)
28 +
29 + unlocker := blocks.GCLock()
30 + defer unlocker.Unlock()
31 +
32 + stillOkay, err := checkIfPinned(pins, cids, out)
33 + if err != nil {
34 + out <- &RemovedBlock{Error: fmt.Sprintf("pin check failed: %s", err)}
35 + return
36 + }
37 +
38 + for _, c := range stillOkay {
39 + err := blocks.DeleteBlock(key.Key(c.Hash()))
40 + if err != nil && opts.Force && (err == bs.ErrNotFound || err == ds.ErrNotFound) {
41 + // ignore non-existent blocks
42 + } else if err != nil {
43 + out <- &RemovedBlock{Hash: c.String(), Error: err.Error()}
44 + } else if !opts.Quiet {
45 + out <- &RemovedBlock{Hash: c.String()}
46 + }
47 + }
48 + }()
49 + return nil
50 +}
51 +
52 +func checkIfPinned(pins pin.Pinner, cids []*cid.Cid, out chan<- interface{}) ([]*cid.Cid, error) {
53 + stillOkay := make([]*cid.Cid, 0, len(cids))
54 + res, err := pins.CheckIfPinned(cids...)
55 + if err != nil {
56 + return nil, err
57 + }
58 + for _, r := range res {
59 + if !r.Pinned() {
60 + stillOkay = append(stillOkay, r.Key)
61 + } else {
62 + out <- &RemovedBlock{
63 + Hash: r.Key.String(),
64 + Error: r.String(),
65 + }
66 + }
67 + }
68 + return stillOkay, nil
69 +}
70 +
71 +type RmError struct {
72 + Fatal bool
73 + Msg string
74 +}
75 +
76 +func (err RmError) Error() string { return err.Msg }
77 +
78 +func ProcRmOutput(in <-chan interface{}, sout io.Writer, serr io.Writer) *RmError {
79 + someFailed := false
80 + for res := range in {
81 + r := res.(*RemovedBlock)
82 + if r.Hash == "" && r.Error != "" {
83 + return &RmError{
84 + Fatal: true,
85 + Msg: fmt.Sprintf("aborted: %s", r.Error),
86 + }
87 + } else if r.Error != "" {
88 + someFailed = true
89 + fmt.Fprintf(serr, "cannot remove %s: %s\n", r.Hash, r.Error)
90 + } else {
91 + fmt.Fprintf(sout, "removed %s\n", r.Hash)
92 + }
93 + }
94 + if someFailed {
95 + return &RmError{
96 + Msg: fmt.Sprintf("some blocks not removed"),
97 + }
98 + }
99 + return nil
100 +}
core/commands/block.go
+13 -83
@@ -9,12 +9,9 @@ import (
9 "strings"
10
11 "github.com/ipfs/go-ipfs/blocks"
12 - bs "github.com/ipfs/go-ipfs/blocks/blockstore"
12 + util "github.com/ipfs/go-ipfs/blocks/blockstore/util"
13 cmds "github.com/ipfs/go-ipfs/commands"
14 - "github.com/ipfs/go-ipfs/pin"
14 u "gx/ipfs/QmZNVWh8LLjAavuQ2JXuFmuYH3C11xo988vSgp7UQrTRj1/go-ipfs-util"
16 - ds "gx/ipfs/QmbzuUusHqaLLoNTDEVLcSF6vZDHZDLPC7p4bztRvvkXxU/go-datastore"
17 - key "gx/ipfs/Qmce4Y4zg3sYr7xKM5UueS67vhNni6EeWgCRnb7MbLJMew/go-key"
15 cid "gx/ipfs/QmfSc2xehWmWLnwwYR91Y8QF4xdASypTFVknutoKQS3GHp/go-cid"
16 )
17
@@ -224,19 +221,15 @@ It takes a list of base58 encoded multihashs to remove.
221 cids = append(cids, c)
222 }
223 outChan := make(chan interface{})
224 + err = util.RmBlocks(n.Blockstore, n.Pinning, outChan, cids, util.RmBlocksOpts{
225 + Quiet: quiet,
226 + Force: force,
227 + })
228 + if err != nil {
229 + res.SetError(err, cmds.ErrNormal)
230 + return
231 + }
232 res.SetOutput((<-chan interface{})(outChan))
228 - go func() {
229 - defer close(outChan)
230 - pinning := n.Pinning
231 - err := rmBlocks(n.Blockstore, pinning, outChan, cids, rmBlocksOpts{
232 - quiet: quiet,
233 - force: force,
234 - })
235 - if err != nil {
236 - outChan <- &RemovedBlock{Error: err.Error()}
237 - }
238 - }()
239 - return
233 },
234 PostRun: func(req cmds.Request, res cmds.Response) {
235 if res.Error() != nil {
@@ -249,73 +242,10 @@ It takes a list of base58 encoded multihashs to remove.
242 }
243 res.SetOutput(nil)
244
252 - someFailed := false
253 - for out := range outChan {
254 - o := out.(*RemovedBlock)
255 - if o.Hash == "" && o.Error != "" {
256 - res.SetError(fmt.Errorf("aborted: %s", o.Error), cmds.ErrNormal)
257 - return
258 - } else if o.Error != "" {
259 - someFailed = true
260 - fmt.Fprintf(res.Stderr(), "cannot remove %s: %s\n", o.Hash, o.Error)
261 - } else {
262 - fmt.Fprintf(res.Stdout(), "removed %s\n", o.Hash)
263 - }
264 - }
265 - if someFailed {
266 - res.SetError(fmt.Errorf("some blocks not removed"), cmds.ErrNormal)
245 + err := util.ProcRmOutput(outChan, res.Stdout(), res.Stderr())
246 + if err != nil {
247 + res.SetError(err, cmds.ErrNormal)
248 }
249 },
269 - Type: RemovedBlock{},
270 -}
271 -
272 -type RemovedBlock struct {
273 - Hash string `json:",omitempty"`
274 - Error string `json:",omitempty"`
275 -}
276 -
277 -type rmBlocksOpts struct {
278 - quiet bool
279 - force bool
280 -}
281 -
282 -func rmBlocks(blocks bs.GCBlockstore, pins pin.Pinner, out chan<- interface{}, cids []*cid.Cid, opts rmBlocksOpts) error {
283 - unlocker := blocks.GCLock()
284 - defer unlocker.Unlock()
285 -
286 - stillOkay, err := checkIfPinned(pins, cids, out)
287 - if err != nil {
288 - return fmt.Errorf("pin check failed: %s", err)
289 - }
290 -
291 - for _, c := range stillOkay {
292 - err := blocks.DeleteBlock(key.Key(c.Hash()))
293 - if err != nil && opts.force && (err == bs.ErrNotFound || err == ds.ErrNotFound) {
294 - // ignore non-existent blocks
295 - } else if err != nil {
296 - out <- &RemovedBlock{Hash: c.String(), Error: err.Error()}
297 - } else if !opts.quiet {
298 - out <- &RemovedBlock{Hash: c.String()}
299 - }
300 - }
301 - return nil
302 -}
303 -
304 -func checkIfPinned(pins pin.Pinner, cids []*cid.Cid, out chan<- interface{}) ([]*cid.Cid, error) {
305 - stillOkay := make([]*cid.Cid, 0, len(cids))
306 - res, err := pins.CheckIfPinned(cids...)
307 - if err != nil {
308 - return nil, err
309 - }
310 - for _, r := range res {
311 - if !r.Pinned() {
312 - stillOkay = append(stillOkay, r.Key)
313 - } else {
314 - out <- &RemovedBlock{
315 - Hash: r.Key.String(),
316 - Error: r.String(),
317 - }
318 - }
319 - }
320 - return stillOkay, nil
250 + Type: util.RemovedBlock{},
251 }