..

ipfs-cluster中add的过程

通过 ipfs-cluster-ctl 的命令行形式,看一下 Add 的流程。

1、调用 client 的 Add 方法

cerr := globalClient.Add(ctx, paths, p, out)

2、 defaultClient 中的 Add 实现

func (c *defaultClient) Add(
	ctx context.Context,
	paths []string,
	params *api.AddParams,
	out chan<- *api.AddedOutput,
) error {
	ctx, span := trace.StartSpan(ctx, "client/Add")
	defer span.End()

	addFiles := make([]files.DirEntry, len(paths))
	for i, p := range paths {
		u, err := url.Parse(p)
		if err != nil {
			close(out)
			return fmt.Errorf("error parsing path: %s", err)
		}
		var name string
		var addFile files.Node
		if strings.HasPrefix(u.Scheme, "http") {
			addFile = files.NewWebFile(u)
			name = path.Base(u.Path)
		} else {
			if params.NoCopy {
				close(out)
				return fmt.Errorf("nocopy option is only valid for URLs")
			}
			name, addFile, err = makeSerialFile(p, params)
			if err != nil {
				close(out)
				return err
			}
		}
		addFiles[i] = files.FileEntry(name, addFile)
	}

	sliceFile := files.NewSliceDirectory(addFiles)
	// If `form` is set to true, the multipart data will have
	// a Content-Type of 'multipart/form-data', if `form` is false,
	// the Content-Type will be 'multipart/mixed'.
	return c.AddMultiFile(ctx, files.NewMultiFileReader(sliceFile, true), params, out)
}

3、AddMultiFile

func (c *defaultClient) AddMultiFile(...) {
	err = c.doStream(ctx,
		"POST",
		"/add?"+queryStr,
		headers,
		multiFileR,
		handler,
	)
}

4、doStream

func (c *defaultClient) doStream() {
	resp, err := c.doRequest(ctx, method, path, headers, body)
}

5、doRequest

func (c *defaultClient) doRequest() {
	return c.client.Do(r)
}

以上就是Add的一个比较粗略的过程,细节在debug时候会详解。 其中对于返回值,是通过 chan 来接收的。 看实现

1) 先创建一个带缓冲的通道 out

out := make(chan *api.AddedOutput, 1)

2) 传递该通道进入方法

cerr := globalClient.Add(ctx, paths, p, out)

3) Add 方法的形参

func (c *defaultClient) Add(
	ctx context.Context,
	paths []string,
	params *api.AddParams,
	out chan<- *api.AddedOutput,
) error

可以看到,out 通道只能进行写操作!!!

4) dec out

	handler := func(dec *json.Decoder) error {
		if out == nil {
			return nil
		}
		var obj api.AddedOutput
		err := dec.Decode(&obj)
		if err != nil {
			return err
		}
		out <- &obj
		return nil
	}

通过回调handler,解析返回结果后, 写进out通道,至此,数据返回到了上层。


Nothing