@cryptotaxi247 / kubo / commits / bdc9f6a96

coreapi: implement block API

License: MIT Signed-off-by: Łukasz Magiera <magik6k@gmail.com>

Łukasz Magiera committed Jan 6, 2018 at 16:57 UTC bdc9f6a96adfdac63dd607b1301613a183400eea
4 files changed +202 -6
core/coreapi/block.go new
+131
@@ -0,0 +1,131 @@
1 +package coreapi
2 +
3 +import (
4 + "bytes"
5 + "context"
6 + "errors"
7 + "fmt"
8 + "io"
9 + "io/ioutil"
10 +
11 + util "github.com/ipfs/go-ipfs/blocks/blockstore/util"
12 + coreiface "github.com/ipfs/go-ipfs/core/coreapi/interface"
13 + caopts "github.com/ipfs/go-ipfs/core/coreapi/interface/options"
14 +
15 + blocks "gx/ipfs/QmYsEQydGrsxNZfAiskvQ76N2xE9hDQtSAkRSynwMiUK3c/go-block-format"
16 + cid "gx/ipfs/QmeSrf6pzut73u6zLQkRFQ3ygt3k6XFT2kjdYP8Tnkwwyg/go-cid"
17 +)
18 +
19 +type BlockAPI struct {
20 + *CoreAPI
21 + *caopts.BlockOptions
22 +}
23 +
24 +type BlockStat struct {
25 + path coreiface.Path
26 + size int
27 +}
28 +
29 +func (api *BlockAPI) Put(ctx context.Context, src io.Reader, opts ...caopts.BlockPutOption) (coreiface.Path, error) {
30 + settings, err := caopts.BlockPutOptions(opts...)
31 + if err != nil {
32 + return nil, err
33 + }
34 +
35 + data, err := ioutil.ReadAll(src)
36 + if err != nil {
37 + return nil, err
38 + }
39 +
40 + var pref cid.Prefix
41 + pref.Version = 1
42 +
43 + formatval, ok := cid.Codecs[settings.Codec]
44 + if !ok {
45 + return nil, fmt.Errorf("unrecognized format: %s", settings.Codec)
46 + }
47 + if settings.Codec == "v0" {
48 + pref.Version = 0
49 + }
50 + pref.Codec = formatval
51 +
52 + pref.MhType = settings.MhType
53 + pref.MhLength = settings.MhLength
54 +
55 + bcid, err := pref.Sum(data)
56 + if err != nil {
57 + return nil, err
58 + }
59 +
60 + b, err := blocks.NewBlockWithCid(data, bcid)
61 + if err != nil {
62 + return nil, err
63 + }
64 +
65 + k, err := api.node.Blocks.AddBlock(b)
66 + if err != nil {
67 + return nil, err
68 + }
69 +
70 + return ParseCid(k), nil
71 +}
72 +
73 +func (api *BlockAPI) Get(ctx context.Context, p coreiface.Path) (io.Reader, error) {
74 + b, err := api.node.Blocks.GetBlock(ctx, p.Cid())
75 + if err != nil {
76 + return nil, err
77 + }
78 +
79 + return bytes.NewReader(b.RawData()), nil
80 +}
81 +
82 +func (api *BlockAPI) Rm(ctx context.Context, p coreiface.Path, opts ...caopts.BlockRmOption) error {
83 + settings, err := caopts.BlockRmOptions(opts...)
84 + if err != nil {
85 + return err
86 + }
87 + cids := []*cid.Cid{p.Cid()}
88 + o := util.RmBlocksOpts{Force: settings.Force}
89 +
90 + out, err := util.RmBlocks(api.node.Blockstore, api.node.Pinning, cids, o)
91 + if err != nil {
92 + return err
93 + }
94 +
95 + select {
96 + case res := <-out:
97 + remBlock, ok := res.(*util.RemovedBlock)
98 + if !ok {
99 + return errors.New("got unexpected output from util.RmBlocks")
100 + }
101 +
102 + if remBlock.Error != "" {
103 + return errors.New(remBlock.Error)
104 + }
105 + return nil
106 + case <-ctx.Done():
107 + return ctx.Err()
108 + }
109 +
110 + return nil
111 +}
112 +
113 +func (api *BlockAPI) Stat(ctx context.Context, p coreiface.Path) (coreiface.BlockStat, error) {
114 + b, err := api.node.Blocks.GetBlock(ctx, p.Cid())
115 + if err != nil {
116 + return nil, err
117 + }
118 +
119 + return &BlockStat{
120 + path: ParseCid(b.Cid()),
121 + size: len(b.RawData()),
122 + }, nil
123 +}
124 +
125 +func (bs *BlockStat) Size() int {
126 + return bs.size
127 +}
128 +
129 +func (bs *BlockStat) Path() coreiface.Path {
130 + return bs.path
131 +}
core/coreapi/coreapi.go
+4
@@ -26,6 +26,10 @@ func (api *CoreAPI) Unixfs() coreiface.UnixfsAPI {
26 return (*UnixfsAPI)(api)
27 }
28
29 +func (api *CoreAPI) Block() coreiface.BlockAPI {
30 + return &BlockAPI{api, nil}
31 +}
32 +
33 // Dag returns the DagAPI interface backed by the go-ipfs node
34 func (api *CoreAPI) Dag() coreiface.DagAPI {
35 return &DagAPI{api, nil}
core/coreapi/interface/interface.go
+7 -5
@@ -62,6 +62,8 @@ type BlockStat interface {
62 type CoreAPI interface {
63 // Unixfs returns an implementation of Unixfs API.
64 Unixfs() UnixfsAPI
65 + // Block returns an implementation of Block API.
66 + Block() BlockAPI
67 // Dag returns an implementation of Dag API.
68 Dag() DagAPI
69 // Name returns an implementation of Name API.
@@ -93,16 +95,16 @@ type UnixfsAPI interface {
95 }
96
97 type BlockAPI interface {
96 - Put(context.Context, io.Reader) (Path, error)
97 - WithCodec(codec uint64) options.BlockPutOption
98 + Put(context.Context, io.Reader, ...options.BlockPutOption) (Path, error)
99 + WithFormat(codec string) options.BlockPutOption
100 WithHash(mhType uint64, mhLen int) options.BlockPutOption
101
100 - Get(context.Context) (io.Reader, error)
102 + Get(context.Context, Path) (io.Reader, error)
103
102 - Rm(context.Context) error
104 + Rm(context.Context, Path, ...options.BlockRmOption) error
105 WithForce(force bool) options.BlockRmOption
106
105 - Stat(context.Context) (BlockStat, error)
107 + Stat(context.Context, Path) (BlockStat, error)
108 }
109
110 // DagAPI specifies the interface to IPLD
core/coreapi/interface/options/block.go
+60 -1
@@ -1,7 +1,12 @@
1 package options
2
3 +import (
4 + //cid "gx/ipfs/QmeSrf6pzut73u6zLQkRFQ3ygt3k6XFT2kjdYP8Tnkwwyg/go-cid"
5 + "gx/ipfs/QmYeKnKpubCMRiq3PGZcTREErthbb5Q9cXsCoSkD9bjEBd/go-multihash"
6 +)
7 +
8 type BlockPutSettings struct {
4 - Codec uint64
9 + Codec string
10 MhType uint64
11 MhLength int
12 }
@@ -12,3 +17,57 @@ type BlockRmSettings struct {
17
18 type BlockPutOption func(*BlockPutSettings) error
19 type BlockRmOption func(*BlockRmSettings) error
20 +
21 +func BlockPutOptions(opts ...BlockPutOption) (*BlockPutSettings, error) {
22 + options := &BlockPutSettings{
23 + Codec: "v0",
24 + MhType: multihash.SHA2_256,
25 + MhLength: -1,
26 + }
27 +
28 + for _, opt := range opts {
29 + err := opt(options)
30 + if err != nil {
31 + return nil, err
32 + }
33 + }
34 + return options, nil
35 +}
36 +
37 +func BlockRmOptions(opts ...BlockRmOption) (*BlockRmSettings, error) {
38 + options := &BlockRmSettings{
39 + Force: false,
40 + }
41 +
42 + for _, opt := range opts {
43 + err := opt(options)
44 + if err != nil {
45 + return nil, err
46 + }
47 + }
48 + return options, nil
49 +}
50 +
51 +type BlockOptions struct{}
52 +
53 +func (api *BlockOptions) WithFormat(codec string) BlockPutOption {
54 + return func(settings *BlockPutSettings) error {
55 + settings.Codec = codec
56 + return nil
57 + }
58 +}
59 +
60 +func (api *BlockOptions) WithHash(mhType uint64, mhLen int) BlockPutOption {
61 + return func(settings *BlockPutSettings) error {
62 + settings.MhType = mhType
63 + settings.MhLength = mhLen
64 + return nil
65 + }
66 +}
67 +
68 +func (api *BlockOptions) WithForce(force bool) BlockRmOption {
69 + return func(settings *BlockRmSettings) error {
70 + settings.Force = force
71 + return nil
72 + }
73 +}