kubo/blocks/blockstore/util/remove.go
Jeromy eac13abaec update to new cid and ipld node packages
License: MIT
Signed-off-by: Jeromy <why@ipfs.io>
2016-10-25 09:54:04 -07:00

91 lines
2.4 KiB
Go

package blockstore_util
import (
"fmt"
"io"
bs "github.com/ipfs/go-ipfs/blocks/blockstore"
"github.com/ipfs/go-ipfs/pin"
cid "gx/ipfs/QmXfiyr2RWEXpVDdaYnD2HNiBk6UBddsvEP4RPfXb6nGqY/go-cid"
ds "gx/ipfs/QmbzuUusHqaLLoNTDEVLcSF6vZDHZDLPC7p4bztRvvkXxU/go-datastore"
)
// RemovedBlock is used to respresent the result of removing a block.
// If a block was removed successfully than the Error string will be
// empty. If a block could not be removed than Error will contain the
// reason the block could not be removed. If the removal was aborted
// due to a fatal error Hash will be be empty, Error will contain the
// reason, and no more results will be sent.
type RemovedBlock struct {
Hash string `json:",omitempty"`
Error string `json:",omitempty"`
}
type RmBlocksOpts struct {
Prefix string
Quiet bool
Force bool
}
func RmBlocks(blocks bs.GCBlockstore, pins pin.Pinner, out chan<- interface{}, cids []*cid.Cid, opts RmBlocksOpts) error {
go func() {
defer close(out)
unlocker := blocks.GCLock()
defer unlocker.Unlock()
stillOkay := FilterPinned(pins, out, cids)
for _, c := range stillOkay {
err := blocks.DeleteBlock(c)
if err != nil && opts.Force && (err == bs.ErrNotFound || err == ds.ErrNotFound) {
// ignore non-existent blocks
} else if err != nil {
out <- &RemovedBlock{Hash: c.String(), Error: err.Error()}
} else if !opts.Quiet {
out <- &RemovedBlock{Hash: c.String()}
}
}
}()
return nil
}
func FilterPinned(pins pin.Pinner, out chan<- interface{}, cids []*cid.Cid) []*cid.Cid {
stillOkay := make([]*cid.Cid, 0, len(cids))
res, err := pins.CheckIfPinned(cids...)
if err != nil {
out <- &RemovedBlock{Error: fmt.Sprintf("pin check failed: %s", err)}
return nil
}
for _, r := range res {
if !r.Pinned() {
stillOkay = append(stillOkay, r.Key)
} else {
out <- &RemovedBlock{
Hash: r.Key.String(),
Error: r.String(),
}
}
}
return stillOkay
}
func ProcRmOutput(in <-chan interface{}, sout io.Writer, serr io.Writer) error {
someFailed := false
for res := range in {
r := res.(*RemovedBlock)
if r.Hash == "" && r.Error != "" {
return fmt.Errorf("aborted: %s", r.Error)
} else if r.Error != "" {
someFailed = true
fmt.Fprintf(serr, "cannot remove %s: %s\n", r.Hash, r.Error)
} else {
fmt.Fprintf(sout, "removed %s\n", r.Hash)
}
}
if someFailed {
return fmt.Errorf("some blocks not removed")
}
return nil
}