IPFS(三)源码解读之-add
Add 所作的事其实就是将⽂件传到IPFS上,通过块的⽅式存到本地blockstore中。
在ipfs的安装⽬录的blocks⽬录下保存了当前本地节点所存储的所有的块数据,具体有没有对数据加密,我也没有仔细去看
Ps:我去看了⼀下,并没有加密,原⽂存储,这⾥需要批评⼀下…
⾸先,add的⼊⼝在core/⽂件,这是⼀个命令⾏⼯具,主要作⽤是提供交互以及命令的⼀下定义和相关配置对应的不同功能的解析,这⾥真的只是解析,然后保存到AddedObject这个对象中,这个对象的作⽤就是当上传是的关于⽂件的⼀下配置信息,和⼀些操作。
type AddedObject struct{
Name string
Hash string`json:",omitempty"`
Bytes int64`json:",omitempty"`
Size string`json:",omitempty"`
VID string`json:",omitempty"`
VersionInfo *utils.VersionInfo
}
然后,通过下⾯这种看起来很奇怪的⽅式去上传⽂件的数据量,具体后⾯的块⽣成部分我们不去探讨,这⾥只看是怎么从本地读取到节点,并将这个流送⼊块中的
其实下⾯做的事⾮常简单,先定义好addAllAndPin这个⽅法,这个⽅法最主要的作⽤就是对⽂件路径进⾏遍历,也就是我们在命令⾏输⼊的路径,读取⽂件内容,通过fileAdder.AddFile(file)将⽂件写⼊到下⼀步
⽽下⾯的协程⽤于监听上传是否完成,是否有错误。并将错误信息丢⼊errCh管道,并且关闭output这个管道,
作⽤在于这两个管道被⽤于向控制台输出。output是输出上传情况,上传完成后的块hash等,errCh就是错误信息
目光如豆
addAllAndPin :=func(f files.File)error{
// Iterate over each top-level file and add individually. Otherwi the
// single files.File f is treated as a directory, affecting hidden file
// mantics.
for{
file, err := f.NextFile()
if err == io.EOF {
// Finished the list of files.
break
}el if err !=nil{
return err
}
if err := fileAdder.AddFile(file); err !=nil{
return err
}
}
// copy intermediary nodes from editor to our actual dagrvice
_, err := fileAdder.Finalize()
if err !=nil{
return err
}
if hash {
肘骨return nil
}
return fileAdder.PinRoot()
}
errCh :=make(chan error)
go func(){
var err error
defer func(){ errCh <- err }()
defer clo(outChan)
err =addAllAndPin(req.Files)
}()
defer res.Clo()
err = res.Emit(outChan)
if err !=nil{
log.Error(err)
return
}
err =<-errCh
if err !=nil{
res.SetError(err, cmdkit.ErrNormal)
}
下⾯进⼊具体上传⼯作的函数,也就是fileAdder.AddFile(file),fileAddrer是上⾯⽣成⼀个AddedObjec
t这个结构体的对象,它有⼀些⼯具⽅法,AddFile就是⽤于上传的对外接⼝,在core/⽂件中
func(adder *Adder)AddFile(file files.File)error{
if adder.Pin {
adder.unlocker = adder.blockstore.PinLock()
}
defer func(){
if adder.unlocker !=nil{
adder.unlocker.Unlock()
}大丁香
}()
return adder.addFile(file,fal,nil)
}
主要就是⼏个锁的设置,继续调⽤内部的addFile⽅法,到这⾥其实就以及开始上传了,后⾯的代码就不分析了,有兴趣的⼩伙伴可以⾃⼰去看⼀下
下⾯是命令⾏⼊⼝的全部内容
package commands
import (
“errors”
“fmt”
“io”
“os”
“strings”
点石成金的故事//块服务提供的接⼝
blockrvice “”
//核⼼api
core “”
//add的⼀些⼯具⽅法和结构
“”
//⽂件存储接⼝
filestore “”
//dag服务接⼝
dag “”
//提供⼀个新的线程安全的dag
dagtest “”
/
/⼀个可变IPFS⽂件系统的内存模型
mfs “”
//⽂件系统格式
ft “”
//控制台⼊⼝⼯具包以下都是⼯具包
cmds “gx/ipfs/QmNueRyPRQiV7PUEpnP4GgGLuK1rKQLaRW7sfPvUetYig1/go-ipfs-cmds”
mh “gx/ipfs/QmPnFwZ2JXKnXgMw8CdBPxn7FWh6LLdjUjxV1fKHuJnkr8/go-multihash”
pb “gx/ipfs/QmPtj12fdwuAqj9sBSTNUxBNu8kCGNp8b3o8yUzMm5GHpq/pb”
offline “gx/ipfs/QmS6mo1dPpHdYsVkm27BRZDLxpKBCiJKUH8fHX15XFfMez/go-ipfs-exchange-offline”
bstore “gx/ipfs/QmadMhXJLHMFjpRmh85XjpmVDkEtQpNYEZNRpWRvYVLrvb/go-ipfs-blockstore”
cmdkit “gx/ipfs/QmdE4gMduCKCGAcczM2F5ioYDfdeKuPix138wrES1YSr7f/go-ipfs-cmdkit”
files “gx/ipfs/QmdE4gMduCKCGAcczM2F5ioYDfdeKuPix138wrES1YSr7f/go-ipfs-cmdkit/files”
)
//限制深度 深度达到上限
// ErrDepthLimitExceeded indicates that the max depth has been exceeded.
var ErrDepthLimitExceeded = fmt.Errorf(“depth limit exceeded”)
//构建命令选项参数常量
const (
quietOptionName = “quiet”
quieterOptionName = “quieter”
silentOptionName = “silent”
progressOptionName = “progress”
trickleOptionName = “trickle”
wrapOptionName = “wrap-with-directory”
hiddenOptionName = “hidden”
onlyHashOptionName = “only-hash”
chunkerOptionName = “chunker”
pinOptionName = “pin”
rawLeavesOptionName = “raw-leaves”
noCopyOptionName = “nocopy”
fstoreCacheOptionName = “fscache”
cidVersionOptionName = “cid-version”
hashOptionName = “hash”
)
//管道上限
excel取整函数const adderOutChanSize = 8
//构建⼀个命令
var AddCmd = &cmds.Command{
//命令对应的帮助信息
Helptext: cmdkit.HelpText{
Tagline: “Add a file or directory to ipfs.”,
ShortDescription: Adds contents of <path> to ipfs. U -r to add directories (recursively)., LongDescription: `
Adds contents of to ipfs. U -r to add directories.
Note that directories are added recursively, to form the ipfs
MerkleDAG.
The wrap option, ‘-w’, wraps the file (or files, if using the
recursive option) in a directory. This directory contains only
the files which have been added, and means that the file retains
its filename. For example:
ipfs add example.jpg
added QmbFMke1KXqnYyBBWxB74N4c5SBnJMVAiMNRcGu6x1AwQH example.jpg ipfs add example.jpg -w
added QmbFMke1KXqnYyBBWxB74N4c5SBnJMVAiMNRcGu6x1AwQH example.jpg added QmaG4FuMqEBnQNn3C8XJ5bpW8kLs7zq2ZXgHptJHbKDDVx
You can now refer to the added file in a gateway, like so:
/ipfs/QmaG4FuMqEBnQNn3C8XJ5bpW8kLs7zq2ZXgHptJHbKDDVx/example.jpg
The chunker option, ‘-s’, specifies the chunking strategy that dictates
how to break files into blocks. Blocks with same content can
be deduplicated. The default is a fixed block size of
256 * 1024 bytes, ‘size-262144’. Alternatively, you can u the
rabin chunker for content defined chunking by specifying
rabin-[min]-[avg]-[max] (where min/avg/max refer to the resulting
chunk sizes). Using other chunking strategies will produce
different hashes for the same file.
ipfs add --chunker=size-2048 ipfs-logo.svg
added QmafrLBfzRLV4XSH1XcaMMeaXEUhDJjmtDfsYU95TrWG87 ipfs-logo.svg
ipfs add --chunker=rabin-512-1024-2048 ipfs-logo.svg
added Qmf1hDN65tR55Ubh2RN1FPxr69xq3giVBz1KApsresY8Gn ipfs-logo.svg
You can now check what blocks have been created by:
ipfs object links QmafrLBfzRLV4XSH1XcaMMeaXEUhDJjmtDfsYU95TrWG87
QmY6yj1GrmExDXoosVE3aSPxdMNYr6aKuw3nA8LoWPRS 2059
Qmf7ZQeSxq2fJVJbCmgTrLLVN9tDR9Wy5k75DxQKuz5Gyt 1195
ipfs object links Qmf1hDN65tR55Ubh2RN1FPxr69xq3giVBz1KApsresY8Gn
QmY6yj1GrmExDXoosVE3aSPxdMNYr6aKuw3nA8LoWPRS 2059
QmerURi9k4XzKCaaPbsK6BL5pMEjF7PGphjDvkkjDtsVf3 868
QmQB28iwSriSUSMqG2nXDTLtdPHgWb4rebBrU7Q1j4vxPv 338
`,
},
小狗画法/
/命令对应参数格式
Arguments: []cmdkit.Argument{
cmdkit.FileArg(“path”, true, true, “The path to a file to be added to ipfs.”).EnableRecursive().EnableStdin(), },
//命令参数可选项设置
Options: []cmdkit.Option{
//注意所有带有experimental的命令选项都是实验的部分需要在配置⽂件中启⽤如果需要使⽤测试的话
cmds.OptionRecursivePath, // a builtin option that allows recursive paths (-r, --recursive)
cmdkit.BoolOption(quietOptionName, “q”, “Write minimal output.”),
cmdkit.BoolOption(quieterOptionName, “Q”, “Write only final hash.”),
cmdkit.BoolOption(silentOptionName, “Write no output.”),
cmdkit.BoolOption(progressOptionName, “p”, “Stream progress data.”),
阴唇大怎么回事cmdkit.BoolOption(trickleOptionName, “t”, “U trickle-dag format for dag generation.”),
cmdkit.BoolOption(onlyHashOptionName, “n”, “Only chunk and hash - do not write to disk.”),
cmdkit.BoolOption(wrapOptionName, “w”, “Wrap files with a directory object.”),
cmdkit.BoolOption(hiddenOptionName, “H”, “Include files that are hidden. Only takes effect on recursive add.”), cmdkit.StringOption(chunkerOptionName, “s”, “Chunking algorithm, size-[bytes] or rabin-[min]-[avg]-
[max]”).WithDefault(“size-262144”),
cmdkit.BoolOption(pinOptionName, “Pin this object when adding.”).WithDefault(true),
cmdkit.BoolOption(rawLeavesOptionName, “U raw blocks for leaf nodes. (experimental)”),
cmdkit.BoolOption(noCopyOptionName, “Add the file using filestore. Implies raw-leaves. (experimental)”), cmdkit.BoolOption(fstoreCacheOptionName, “Check the filestore for pre-existing blocks. (experimental)”), cmdkit.IntOption(cidVersionOptionName, “CID version. Defaults to 0 unless an option that depends on CIDv1 is pasd. (experimental)”),
cmdkit.StringOption(hashOptionName, “Hash function to u. Implies CIDv1 if not sha2-256.
(experimental)”).WithDefault(“sha2-256”),
},
//设置命令默认选项的默认值,节点启动时运⾏
PreRun: func(req *cmds.Request, env cmds.Environment) error {
quiet, _ := req.Options[quietOptionName].(bool)
quieter, _ := req.Options[quieterOptionName].(bool)
quiet = quiet || quieter
silent, _ := req.Options[silentOptionName].(bool)诚实近义词
if quiet || silent {
return nil
}
// ipfs cli progress bar defaults to true unless quiet or silent is ud
_, found := req.Options[progressOptionName].(bool)
if !found {
req.Options[progressOptionName] = true
}
return nil