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