@cryptotaxi247 / kubo / commits / 6ad497bcf

"block rm": use channel instead of pipe / don't abort on non-fatal error

License: MIT Signed-off-by: Kevin Atkinson <k@kevina.org>

Kevin Atkinson committed Aug 10, 2016 at 16:53 UTC 6ad497bcf06a831c5017c05a817140a250d04d69
2 files changed +60 -36
core/commands/block.go
+53 -29
@@ -220,67 +220,91 @@ It takes a list of base58 encoded multihashs to remove.
220 k := key.B58KeyDecode(hash)
221 keys = append(keys, k)
222 }
223 - rdr, wtr := io.Pipe()
223 + outChan := make(chan interface{})
224 + res.SetOutput((<-chan interface{})(outChan))
225 go func() {
226 + defer close(outChan)
227 pinning := n.Pinning
228 if ignorePins {
229 pinning = nil
230 }
229 - err := rmBlocks(n.Blockstore, pinning, wtr, keys)
230 - if err != nil {
231 - wtr.CloseWithError(fmt.Errorf("Some blocks not deleted: %s", err))
232 - } else {
233 - wtr.Close()
234 - }
231 + rmBlocks(n.Blockstore, pinning, outChan, keys)
232 }()
236 - res.SetOutput(rdr)
233 return
234 },
239 - Marshalers: cmds.MarshalerMap{
240 - cmds.Text: func(res cmds.Response) (io.Reader, error) {
241 - return res.(io.Reader), nil
242 - },
235 + PostRun: func(req cmds.Request, res cmds.Response) {
236 + if res.Error() != nil {
237 + return
238 + }
239 + outChan, ok := res.Output().(<-chan interface{})
240 + if !ok {
241 + res.SetError(u.ErrCast(), cmds.ErrNormal)
242 + return
243 + }
244 + res.SetOutput(nil)
245 +
246 + someFailed := false
247 + for out := range outChan {
248 + o := out.(*RemovedBlock)
249 + if o.Error != "" {
250 + someFailed = true
251 + fmt.Fprintf(res.Stderr(), "cannot remove %s: %s\n", o.Hash, o.Error)
252 + } else {
253 + fmt.Fprintf(res.Stdout(), "removed %s\n", o.Hash)
254 + }
255 + }
256 + if someFailed {
257 + res.SetError(fmt.Errorf("some blocks not removed"), cmds.ErrNormal)
258 + }
259 },
260 + Type: RemovedBlock{},
261 +}
262 +
263 +type RemovedBlock struct {
264 + Hash string
265 + Error string `json:",omitempty"`
266 }
267
268 // pins may be nil
247 -func rmBlocks(blocks bs.GCBlockstore, pins pin.Pinner, out io.Writer, keys []key.Key) error {
269 +func rmBlocks(blocks bs.GCBlockstore, pins pin.Pinner, out chan<- interface{}, keys []key.Key) {
270 var unlocker bs.Unlocker
271 defer func() {
272 if unlocker != nil {
273 unlocker.Unlock()
274 }
275 }()
276 + stillOkay := keys
277 if pins != nil {
278 // Need to make sure that some operation that is
279 // finishing with a pin is ocurr simultaneously.
280 unlocker = blocks.GCLock()
258 - err := checkIfPinned(pins, keys)
259 - if err != nil {
260 - return err
261 - }
281 + stillOkay = checkIfPinned(pins, keys, out)
282 }
263 - for _, k := range keys {
283 + for _, k := range stillOkay {
284 err := blocks.DeleteBlock(k)
285 if err != nil {
266 - return fmt.Errorf("%s: %s", k, err)
267 - }
268 - if out != nil {
269 - fmt.Fprintf(out, "deleted %s\n", k)
286 + out <- &RemovedBlock{ Hash: k.String(), Error: err.Error()}
287 + } else {
288 + out <- &RemovedBlock{ Hash: k.String() }
289 }
290 }
272 - return nil
291 }
292
275 -func checkIfPinned(pins pin.Pinner, keys []key.Key) error {
293 +func checkIfPinned(pins pin.Pinner, keys []key.Key, out chan<- interface{}) []key.Key {
294 + stillOkay := make([]key.Key, 0, len(keys))
295 for _, k := range keys {
296 reason, pinned, err := pins.IsPinned(k)
297 if err != nil {
279 - return err
280 - }
281 - if pinned {
282 - return fmt.Errorf("%s pinned via %s", k, reason)
298 + out <- &RemovedBlock {
299 + Hash: k.String(),
300 + Error: fmt.Sprintf("pin check failed %s", err.Error()) }
301 + } else if pinned {
302 + out <- &RemovedBlock {
303 + Hash: k.String(),
304 + Error: fmt.Sprintf("pinned via %s", reason) }
305 + } else {
306 + stillOkay = append(stillOkay, k)
307 }
308 }
285 - return nil
309 + return stillOkay
310 }
test/sharness/t0050-block.sh
+7 -7
@@ -44,7 +44,7 @@ test_expect_success "'ipfs block rm' succeeds" '
44 '
45
46 test_expect_success "'ipfs block rm' output looks good" '
47 - echo "deleted $HASH" > expected_rm &&
47 + echo "removed $HASH" > expected_rm &&
48 test_cmp expected_rm actual_rm
49 '
50
@@ -71,7 +71,7 @@ test_expect_success "can't remove pinned block" '
71 '
72
73 test_expect_success "can't remove pinned block: output looks good" '
74 - grep -q "$DIRHASH pinned via recursive" block_rm_err
74 + grep -q "$DIRHASH: pinned via recursive" block_rm_err
75 '
76
77 test_expect_success "can't remove indirectly pinned block" '
@@ -79,7 +79,7 @@ test_expect_success "can't remove indirectly pinned block" '
79 '
80
81 test_expect_success "can't remove indirectly pinned block: output looks good" '
82 - grep -q "$FILE1HASH pinned via $DIRHASH" block_rm_err
82 + grep -q "$FILE1HASH: pinned via $DIRHASH" block_rm_err
83 '
84
85 test_expect_success "multi-block 'ipfs block rm --ignore-pins' succeeds" '
@@ -87,7 +87,7 @@ test_expect_success "multi-block 'ipfs block rm --ignore-pins' succeeds" '
87 '
88
89 test_expect_success "multi-block 'ipfs block rm --ignore-pins' output looks good" '
90 - echo "deleted $DIRHASH" > expected_rm &&
90 + echo "removed $DIRHASH" > expected_rm &&
91 test_cmp expected_rm actual_rm
92 '
93
@@ -100,9 +100,9 @@ test_expect_success "multi-block 'ipfs block rm' succeeds" '
100 '
101
102 test_expect_success "multi-block 'ipfs block rm' output looks good" '
103 - echo "deleted $FILE1HASH" > expected_rm &&
104 - echo "deleted $FILE2HASH" >> expected_rm &&
105 - echo "deleted $FILE3HASH" >> expected_rm &&
103 + echo "removed $FILE1HASH" > expected_rm &&
104 + echo "removed $FILE2HASH" >> expected_rm &&
105 + echo "removed $FILE3HASH" >> expected_rm &&
106 test_cmp expected_rm actual_rm
107 '
108