Commit bdc9f6a9 authored by Łukasz Magiera's avatar Łukasz Magiera

coreapi: implement block API

License: MIT
Signed-off-by: default avatarŁukasz Magiera <magik6k@gmail.com>
parent 219eae76
package coreapi
import (
"bytes"
"context"
"errors"
"fmt"
"io"
"io/ioutil"
util "github.com/ipfs/go-ipfs/blocks/blockstore/util"
coreiface "github.com/ipfs/go-ipfs/core/coreapi/interface"
caopts "github.com/ipfs/go-ipfs/core/coreapi/interface/options"
blocks "gx/ipfs/QmYsEQydGrsxNZfAiskvQ76N2xE9hDQtSAkRSynwMiUK3c/go-block-format"
cid "gx/ipfs/QmeSrf6pzut73u6zLQkRFQ3ygt3k6XFT2kjdYP8Tnkwwyg/go-cid"
)
type BlockAPI struct {
*CoreAPI
*caopts.BlockOptions
}
type BlockStat struct {
path coreiface.Path
size int
}
func (api *BlockAPI) Put(ctx context.Context, src io.Reader, opts ...caopts.BlockPutOption) (coreiface.Path, error) {
settings, err := caopts.BlockPutOptions(opts...)
if err != nil {
return nil, err
}
data, err := ioutil.ReadAll(src)
if err != nil {
return nil, err
}
var pref cid.Prefix
pref.Version = 1
formatval, ok := cid.Codecs[settings.Codec]
if !ok {
return nil, fmt.Errorf("unrecognized format: %s", settings.Codec)
}
if settings.Codec == "v0" {
pref.Version = 0
}
pref.Codec = formatval
pref.MhType = settings.MhType
pref.MhLength = settings.MhLength
bcid, err := pref.Sum(data)
if err != nil {
return nil, err
}
b, err := blocks.NewBlockWithCid(data, bcid)
if err != nil {
return nil, err
}
k, err := api.node.Blocks.AddBlock(b)
if err != nil {
return nil, err
}
return ParseCid(k), nil
}
func (api *BlockAPI) Get(ctx context.Context, p coreiface.Path) (io.Reader, error) {
b, err := api.node.Blocks.GetBlock(ctx, p.Cid())
if err != nil {
return nil, err
}
return bytes.NewReader(b.RawData()), nil
}
func (api *BlockAPI) Rm(ctx context.Context, p coreiface.Path, opts ...caopts.BlockRmOption) error {
settings, err := caopts.BlockRmOptions(opts...)
if err != nil {
return err
}
cids := []*cid.Cid{p.Cid()}
o := util.RmBlocksOpts{Force: settings.Force}
out, err := util.RmBlocks(api.node.Blockstore, api.node.Pinning, cids, o)
if err != nil {
return err
}
select {
case res := <-out:
remBlock, ok := res.(*util.RemovedBlock)
if !ok {
return errors.New("got unexpected output from util.RmBlocks")
}
if remBlock.Error != "" {
return errors.New(remBlock.Error)
}
return nil
case <-ctx.Done():
return ctx.Err()
}
return nil
}
func (api *BlockAPI) Stat(ctx context.Context, p coreiface.Path) (coreiface.BlockStat, error) {
b, err := api.node.Blocks.GetBlock(ctx, p.Cid())
if err != nil {
return nil, err
}
return &BlockStat{
path: ParseCid(b.Cid()),
size: len(b.RawData()),
}, nil
}
func (bs *BlockStat) Size() int {
return bs.size
}
func (bs *BlockStat) Path() coreiface.Path {
return bs.path
}
......@@ -26,6 +26,10 @@ func (api *CoreAPI) Unixfs() coreiface.UnixfsAPI {
return (*UnixfsAPI)(api)
}
func (api *CoreAPI) Block() coreiface.BlockAPI {
return &BlockAPI{api, nil}
}
// Dag returns the DagAPI interface backed by the go-ipfs node
func (api *CoreAPI) Dag() coreiface.DagAPI {
return &DagAPI{api, nil}
......
......@@ -62,6 +62,8 @@ type BlockStat interface {
type CoreAPI interface {
// Unixfs returns an implementation of Unixfs API.
Unixfs() UnixfsAPI
// Block returns an implementation of Block API.
Block() BlockAPI
// Dag returns an implementation of Dag API.
Dag() DagAPI
// Name returns an implementation of Name API.
......@@ -93,16 +95,16 @@ type UnixfsAPI interface {
}
type BlockAPI interface {
Put(context.Context, io.Reader) (Path, error)
WithCodec(codec uint64) options.BlockPutOption
Put(context.Context, io.Reader, ...options.BlockPutOption) (Path, error)
WithFormat(codec string) options.BlockPutOption
WithHash(mhType uint64, mhLen int) options.BlockPutOption
Get(context.Context) (io.Reader, error)
Get(context.Context, Path) (io.Reader, error)
Rm(context.Context) error
Rm(context.Context, Path, ...options.BlockRmOption) error
WithForce(force bool) options.BlockRmOption
Stat(context.Context) (BlockStat, error)
Stat(context.Context, Path) (BlockStat, error)
}
// DagAPI specifies the interface to IPLD
......
package options
import (
//cid "gx/ipfs/QmeSrf6pzut73u6zLQkRFQ3ygt3k6XFT2kjdYP8Tnkwwyg/go-cid"
"gx/ipfs/QmYeKnKpubCMRiq3PGZcTREErthbb5Q9cXsCoSkD9bjEBd/go-multihash"
)
type BlockPutSettings struct {
Codec uint64
Codec string
MhType uint64
MhLength int
}
......@@ -12,3 +17,57 @@ type BlockRmSettings struct {
type BlockPutOption func(*BlockPutSettings) error
type BlockRmOption func(*BlockRmSettings) error
func BlockPutOptions(opts ...BlockPutOption) (*BlockPutSettings, error) {
options := &BlockPutSettings{
Codec: "v0",
MhType: multihash.SHA2_256,
MhLength: -1,
}
for _, opt := range opts {
err := opt(options)
if err != nil {
return nil, err
}
}
return options, nil
}
func BlockRmOptions(opts ...BlockRmOption) (*BlockRmSettings, error) {
options := &BlockRmSettings{
Force: false,
}
for _, opt := range opts {
err := opt(options)
if err != nil {
return nil, err
}
}
return options, nil
}
type BlockOptions struct{}
func (api *BlockOptions) WithFormat(codec string) BlockPutOption {
return func(settings *BlockPutSettings) error {
settings.Codec = codec
return nil
}
}
func (api *BlockOptions) WithHash(mhType uint64, mhLen int) BlockPutOption {
return func(settings *BlockPutSettings) error {
settings.MhType = mhType
settings.MhLength = mhLen
return nil
}
}
func (api *BlockOptions) WithForce(force bool) BlockRmOption {
return func(settings *BlockRmSettings) error {
settings.Force = force
return nil
}
}
Markdown is supported
0% or .
You are about to add 0 people to the discussion. Proceed with caution.
Finish editing this message first!
Please register or to comment