"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
}