IPFS中的filestore作用類似於Git中的LFS,主要用於存儲大文件,在blockstore只存儲大文件的dag root,在FileManager存放文件的metadata, 避免大文件充斥blockstore,節省blockstore的空間。
Git LFS
LFS全稱Large File System,是git用來存放大文件的地方。它有幾個優點:
1、在git倉庫只存儲了大文件的鏈接(主要存放文件的sha256),體積很小,方便clone和pull。
clone的時候只pull最新的版本,無需像其它object一樣保存所有歷史版本。
2、git diff基於文本行比較,而大文件大部分是二進制文件,diff不適用。
ipfs filestore
filestore結構體如下
// Filestore implements a Blockstore by combining a standard Blockstore
// to store regular blocks and a special Blockstore called
// FileManager to store blocks which data exists in an external file.
type Filestore struct {
fm *FileManager
bs blockstore.Blockstore
}
從代碼註釋可以看出,blockstore用於存儲普通文件(ipfs add file);FileManager用於存儲外部文件地址等信息(ipfs add file --nocopy)。
FileManager和git lfs都是直接管理磁盤上的文件(沒有額外的格式),不同的是,git lfs會copy文件,管理的是lfs倉庫中的文件,存有該文件的所有版本,可以管理版本;而FileManager不copy文件,管理的是源文件,無法管理版本。
FileManager和git lfs都會記錄源文件的metadata,git lfs主要記錄文件路徑(包含文件名)、文件大小及文件內容的哈希(sha256);FileManager主要記錄中key是文件CID的base32編碼,value是文件內容的哈希、路徑(包含文件名)、大小、偏移量(主要用於大文件分塊)和文件stat信息。
FileManager和git lfs雖然都記錄了源文件的metadata及其歷史版本信息,但是git lfs依賴git,可以管理版本(checkout),FileManager不行(只記錄所有歷史版本信息,沒有形成版本鏈條)。
// PosInfo stores information about the file offset, its path and
// stat.
type PosInfo struct {
Offset uint64
FullPath string
Stat os.FileInfo // can be nil
}
// FilestoreNode is an ipld.Node which arries PosInfo with it
// allowing to map it directly to a filesystem object.
type FilestoreNode struct {
ipld.Node
PosInfo *PosInfo
}
實操
準備
1、修改ipfs config配置文件
"Experimental": {
"FilestoreEnabled": false,
"UrlstoreEnabled": false,
}
以上兩個功能默認是關閉的,均設置爲true。
2、add的時候添加–nocopy參數
ipfs filestore命令
$ ipfs filestore -h
USAGE
ipfs filestore - Interact with filestore objects.
ipfs filestore
SUBCOMMANDS
ipfs filestore dups - List blocks that are both in the filestore and standard block storage.
ipfs filestore ls [<obj>]... - List objects in filestore.
ipfs filestore verify [<obj>]... - Verify objects in filestore.
For more information about each command, use:
'ipfs filestore <subcmd> --help'
現階段filestore有3個子命令:dups/ls/verify
add --nocopy
$ echo "Hello" > hello
$ ipfs add hello --nocopy
added bafkreidgubc3iuqqfrm5qqhmbf6vtwkgpyj2h42pmskokop72mwbxm27da hello
有兩點需要注意:
1、只能add文件,不能add字符串 2、add的文件的路徑必須位於ipfs root(默認是$home)底下,可以位於root的多級子目錄。
ipfs add時,ipfs使用FileManager保存文件信息的同時,也會通過dht向距離該文件CID最近的節點provide。
ipfs filestore ls
$ ipfs filestore ls
bafkreidgubc3iuqqfrm5qqhmbf6vtwkgpyj2h42pmskokop72mwbxm27da 6 Downloads/hello 0
ipfs filestore verify
$ ipfs filestore verify bafkreidgubc3iuqqfrm5qqhmbf6vtwkgpyj2h42pmskokop72mwbxm27da
ok bafkreidgubc3iuqqfrm5qqhmbf6vtwkgpyj2h42pmskokop72mwbxm27da 6 Downloads/hello 0
ipfs cat
$ ipfs cat bafkreidgubc3iuqqfrm5qqhmbf6vtwkgpyj2h42pmskokop72mwbxm27da
Hello
最好在linux下ipfs cat,在windows不能直接ipfs cat,只能先get後cat。
由於ipfs1在add的時候已經provide,ipfs2也能cat,即通過bitswap找ipfs發送wantlist請求,獲取文件。
$ echo "Hello World!" > hello
$ ipfs add hello --nocopy
added bafkreiadxiqe4ugre3sgotaalycnqlueyijwm6ak6h2dxvkkg6aww2vtia hello
$ ipfs filestore ls
bafkreidgubc3iuqqfrm5qqhmbf6vtwkgpyj2h42pmskokop72mwbxm27da 6 Downloads/hello 0
bafkreiadxiqe4ugre3sgotaalycnqlueyijwm6ak6h2dxvkkg6aww2vtia 13 Downloads/hello 0
$ ipfs filestore verify bafkreiadxiqe4ugre3sgotaalycnqlueyijwm6ak6h2dxvkkg6aww2vtia
ok bafkreiadxiqe4ugre3sgotaalycnqlueyijwm6ak6h2dxvkkg6aww2vtia 13 Downloads/hello 0
$ ipfs filestore verify bafkreidgubc3iuqqfrm5qqhmbf6vtwkgpyj2h42pmskokop72mwbxm27da
changed bafkreidgubc3iuqqfrm5qqhmbf6vtwkgpyj2h42pmskokop72mwbxm27da 6 Downloads/hello 0
重新add --nocopy後,bafkreidgubc3iuqqfrm5qqhmbf6vtwkgpyj2h42pmskokop72mwbxm27da標註爲"changed",表明已被修改;bafkreiadxiqe4ugre3sgotaalycnqlueyijwm6ak6h2dxvkkg6aww2vtia標註爲"ok",表明是最新版本。
此時我們再ipfs cat下
$ ipfs cat bafkreidgubc3iuqqfrm5qqhmbf6vtwkgpyj2h42pmskokop72mwbxm27da
Error: data in file did not match. Downloads/hello offset 0
$ ipfs cat bafkreiadxiqe4ugre3sgotaalycnqlueyijwm6ak6h2dxvkkg6aww2vtia
Hello World!
果然,bafkreidgubc3iuqqfrm5qqhmbf6vtwkgpyj2h42pmskokop72mwbxm27da的內容已經無法獲取,bafkreiadxiqe4ugre3sgotaalycnqlueyijwm6ak6h2dxvkkg6aww2vtia的內容可以獲取。 因爲Downloads/hello源文件已經改變,無法得知舊版本的內容,只能獲取最新的內容。
有趣的測試
add 大文件(2.16MB)
$ ipfs add IMG_5152.JPG --nocopy
added QmaSDkQpknQeN1iM34SaV8eznkQuuvFHS33zigjCyGnrxa IMG_5152.JPG
2.16 MiB / 2.16 MiB 100.00%
$ ipfs filestore ls
bafkreiaxtlgx2cligrkinkgq6374kd25q2hrbsessdxlzkxd7seh2mrqqq 262144 ipTest/IMG_5152.JPG 1835008
bafkreib5755rqduckwwysb3tkjdlhqt3slkqfkxx7dwihrhko6ezpqizq4 262144 ipTest/IMG_5152.JPG 786432
bafkreic3idfydr2s5wpblk5jmcqdm4d7hu5w3zat73vygswpmomlh37o74 262144 ipTest/IMG_5152.JPG 1310720
bafkreictqthw2fhcxvfwitz5xzjth2if7o534pje6zwfvb52ojv4tpzdw4 262144 ipTest/IMG_5152.JPG 1048576
bafkreiewb3z4zviruicvplcqmsnhqheue3lb44vm335vo4t2h3htz7b7l4 262144 ipTest/IMG_5152.JPG 524288
bafkreif3yikabcsik7wqodrpfeiwjzggbpgmii4kum7otchsnz3ri334zy 262144 ipTest/IMG_5152.JPG 0
bafkreiflbeifymhqb6il5t7kbmlrhtlxjeruztv5bujldrtcgfxksnktmq 262144 ipTest/IMG_5152.JPG 262144
bafkreigfn7y3au6ie4qfrs2njypwp5z52eske7m7bwvzozzqcsvubpmynm 171316 ipTest/IMG_5152.JPG 2097152
bafkreih6hyyn6w4swilsr3aibki4wzqbjqjgr2uxlhewaoodc3twaa4rsm 262144 ipTest/IMG_5152.JPG 1572864
add 目錄
$ mkdir test
$ cd test
$ echo "3" > 3
$ echo "4" > 4
$ cd ..
$ ipfs add test/ -r --nocopy
added bafkreiarehh4zvmrh4fgh7webjx72rhkmt45ye24mzruxiab2ef46qycui test/3
added bafkreid54fkv34gcoabst2avxe5tfrlrypvfjxewpoe6qgvxhomxfnzndu test/4
added QmcdtREQsVfNc3RatR2PwR7i3VuSeLfNND5vGXYNL1sgrx test
4 B / 4 B 100.00%
可見,FileManager只存儲文件,目錄和大文件的dag root依然保存在blockstore中, 這些dag root記錄這目錄內的文件信息以及大文件的分塊信息。