Skip to content
项目
群组
代码片段
帮助
当前项目
正在载入...
登录 / 注册
切换导航面板
G
go-ipfs
概览
概览
详情
活动
周期分析
版本库
仓库
文件
提交
分支
标签
贡献者
分支图
比较
统计图
问题
0
议题
0
列表
看板
标记
里程碑
合并请求
0
合并请求
0
CI / CD
CI / CD
流水线
作业
日程表
图表
维基
Wiki
代码片段
代码片段
成员
成员
折叠边栏
关闭边栏
活动
图像
聊天
创建新问题
作业
提交
问题看板
Open sidebar
jihao
go-ipfs
Commits
07feeec9
Unverified
提交
07feeec9
authored
7月 16, 2018
作者:
Whyrusleeping
提交者:
GitHub
7月 16, 2018
浏览文件
操作
浏览文件
下载
差异文件
Merge pull request #5010 from ipfs/feat/diskusage2
Efficient "repo stat" (DiskUsage) and "--size-only" flag
上级
4f1391f4
9c8d994c
隐藏空白字符变更
内嵌
并排
正在显示
4 个修改的文件
包含
98 行增加
和
65 行删除
+98
-65
repo.go
core/commands/repo.go
+46
-27
stat.go
core/corerepo/stat.go
+38
-15
fsrepo.go
repo/fsrepo/fsrepo.go
+2
-23
t0080-repo.sh
test/sharness/t0080-repo.sh
+12
-0
没有找到文件。
core/commands/repo.go
浏览文件 @
07feeec9
...
@@ -150,14 +150,20 @@ var repoStatCmd = &cmds.Command{
...
@@ -150,14 +150,20 @@ var repoStatCmd = &cmds.Command{
Helptext
:
cmdkit
.
HelpText
{
Helptext
:
cmdkit
.
HelpText
{
Tagline
:
"Get stats for the currently used repo."
,
Tagline
:
"Get stats for the currently used repo."
,
ShortDescription
:
`
ShortDescription
:
`
'ipfs repo stat' is a plumbing command that will scan the local
'ipfs repo stat' provides information about the local set of
set of stored objects and print repo statistics. It outputs to stdout:
stored objects. It outputs:
RepoSize int Size in bytes that the repo is currently taking.
StorageMax string Maximum datastore size (from configuration)
NumObjects int Number of objects in the local repo.
NumObjects int Number of objects in the local repo.
RepoPath string The path to the repo being currently used.
RepoPath string The path to the repo being currently used.
RepoSize int Size in bytes that the repo is currently taking.
Version string The repo version.
Version string The repo version.
`
,
`
,
},
},
Options
:
[]
cmdkit
.
Option
{
cmdkit
.
BoolOption
(
"size-only"
,
"Only report RepoSize and StorageMax."
),
cmdkit
.
BoolOption
(
"human"
,
"Output sizes in MiB."
),
},
Run
:
func
(
req
*
cmds
.
Request
,
res
cmds
.
ResponseEmitter
,
env
cmds
.
Environment
)
{
Run
:
func
(
req
*
cmds
.
Request
,
res
cmds
.
ResponseEmitter
,
env
cmds
.
Environment
)
{
n
,
err
:=
GetNode
(
env
)
n
,
err
:=
GetNode
(
env
)
if
err
!=
nil
{
if
err
!=
nil
{
...
@@ -165,18 +171,28 @@ Version string The repo version.
...
@@ -165,18 +171,28 @@ Version string The repo version.
return
return
}
}
stat
,
err
:=
corerepo
.
RepoStat
(
n
,
req
.
Context
)
sizeOnly
,
_
:=
req
.
Options
[
"size-only"
]
.
(
bool
)
if
sizeOnly
{
sizeStat
,
err
:=
corerepo
.
RepoSize
(
req
.
Context
,
n
)
if
err
!=
nil
{
res
.
SetError
(
err
,
cmdkit
.
ErrNormal
)
return
}
cmds
.
EmitOnce
(
res
,
&
corerepo
.
Stat
{
SizeStat
:
sizeStat
,
})
return
}
stat
,
err
:=
corerepo
.
RepoStat
(
req
.
Context
,
n
)
if
err
!=
nil
{
if
err
!=
nil
{
res
.
SetError
(
err
,
cmdkit
.
ErrNormal
)
res
.
SetError
(
err
,
cmdkit
.
ErrNormal
)
return
return
}
}
cmds
.
EmitOnce
(
res
,
stat
)
cmds
.
EmitOnce
(
res
,
&
stat
)
},
Options
:
[]
cmdkit
.
Option
{
cmdkit
.
BoolOption
(
"human"
,
"Output RepoSize in MiB."
),
},
},
Type
:
corerepo
.
Stat
{},
Type
:
&
corerepo
.
Stat
{},
Encoders
:
cmds
.
EncoderMap
{
Encoders
:
cmds
.
EncoderMap
{
cmds
.
Text
:
cmds
.
MakeEncoder
(
func
(
req
*
cmds
.
Request
,
w
io
.
Writer
,
v
interface
{})
error
{
cmds
.
Text
:
cmds
.
MakeEncoder
(
func
(
req
*
cmds
.
Request
,
w
io
.
Writer
,
v
interface
{})
error
{
stat
,
ok
:=
v
.
(
*
corerepo
.
Stat
)
stat
,
ok
:=
v
.
(
*
corerepo
.
Stat
)
...
@@ -184,31 +200,34 @@ Version string The repo version.
...
@@ -184,31 +200,34 @@ Version string The repo version.
return
e
.
TypeErr
(
stat
,
v
)
return
e
.
TypeErr
(
stat
,
v
)
}
}
human
,
_
:=
req
.
Options
[
"human"
]
.
(
bool
)
wtr
:=
tabwriter
.
NewWriter
(
w
,
0
,
0
,
1
,
' '
,
0
)
wtr
:=
tabwriter
.
NewWriter
(
w
,
0
,
0
,
1
,
' '
,
0
)
defer
wtr
.
Flush
()
fmt
.
Fprintf
(
wtr
,
"NumObjects:
\t
%d
\n
"
,
stat
.
NumObjects
)
human
,
_
:=
req
.
Options
[
"human"
]
.
(
bool
)
sizeInMiB
:=
stat
.
RepoSize
/
(
1024
*
1024
)
sizeOnly
,
_
:=
req
.
Options
[
"size-only"
]
.
(
bool
)
if
human
&&
sizeInMiB
>
0
{
fmt
.
Fprintf
(
wtr
,
"RepoSize (MiB):
\t
%d
\n
"
,
sizeInMiB
)
printSize
:=
func
(
name
string
,
size
uint64
)
{
}
else
{
sizeInMiB
:=
size
/
(
1024
*
1024
)
fmt
.
Fprintf
(
wtr
,
"RepoSize:
\t
%d
\n
"
,
stat
.
RepoSize
)
if
human
&&
sizeInMiB
>
0
{
}
fmt
.
Fprintf
(
wtr
,
"%s (MiB):
\t
%d
\n
"
,
name
,
sizeInMiB
)
if
stat
.
StorageMax
!=
corerepo
.
NoLimit
{
maxSizeInMiB
:=
stat
.
StorageMax
/
(
1024
*
1024
)
if
human
&&
maxSizeInMiB
>
0
{
fmt
.
Fprintf
(
wtr
,
"StorageMax (MiB):
\t
%d
\n
"
,
maxSizeInMiB
)
}
else
{
}
else
{
fmt
.
Fprintf
(
wtr
,
"
StorageMax:
\t
%d
\n
"
,
stat
.
StorageMax
)
fmt
.
Fprintf
(
wtr
,
"
%s:
\t
%d
\n
"
,
name
,
size
)
}
}
}
}
fmt
.
Fprintf
(
wtr
,
"RepoPath:
\t
%s
\n
"
,
stat
.
RepoPath
)
fmt
.
Fprintf
(
wtr
,
"Version:
\t
%s
\n
"
,
stat
.
Version
)
wtr
.
Flush
()
return
nil
if
!
sizeOnly
{
fmt
.
Fprintf
(
wtr
,
"NumObjects:
\t
%d
\n
"
,
stat
.
NumObjects
)
}
printSize
(
"RepoSize"
,
stat
.
RepoSize
)
printSize
(
"StorageMax"
,
stat
.
StorageMax
)
if
!
sizeOnly
{
fmt
.
Fprintf
(
wtr
,
"RepoPath:
\t
%s
\n
"
,
stat
.
RepoPath
)
fmt
.
Fprintf
(
wtr
,
"Version:
\t
%s
\n
"
,
stat
.
Version
)
}
return
nil
}),
}),
},
},
}
}
...
...
core/corerepo/stat.go
浏览文件 @
07feeec9
...
@@ -5,34 +5,40 @@ import (
...
@@ -5,34 +5,40 @@ import (
"math"
"math"
context
"context"
context
"context"
"github.com/ipfs/go-ipfs/core"
"github.com/ipfs/go-ipfs/core"
fsrepo
"github.com/ipfs/go-ipfs/repo/fsrepo"
fsrepo
"github.com/ipfs/go-ipfs/repo/fsrepo"
humanize
"gx/ipfs/QmPSBJL4momYnE7DcUyk2DVhD6rH488ZmHBGLbxNdhU44K/go-humanize"
humanize
"gx/ipfs/QmPSBJL4momYnE7DcUyk2DVhD6rH488ZmHBGLbxNdhU44K/go-humanize"
)
)
// SizeStat wraps information about the repository size and its limit.
type
SizeStat
struct
{
RepoSize
uint64
// size in bytes
StorageMax
uint64
// size in bytes
}
// Stat wraps information about the objects stored on disk.
type
Stat
struct
{
type
Stat
struct
{
SizeStat
NumObjects
uint64
NumObjects
uint64
RepoSize
uint64
// size in bytes
RepoPath
string
RepoPath
string
Version
string
Version
string
StorageMax
uint64
// size in bytes
}
}
// NoLimit represents the value for unlimited storage
// NoLimit represents the value for unlimited storage
const
NoLimit
uint64
=
math
.
MaxUint64
const
NoLimit
uint64
=
math
.
MaxUint64
func
RepoStat
(
n
*
core
.
IpfsNode
,
ctx
context
.
Context
)
(
*
Stat
,
error
)
{
// RepoStat returns a *Stat object with all the fields set.
r
:=
n
.
Repo
func
RepoStat
(
ctx
context
.
Context
,
n
*
core
.
IpfsNode
)
(
Stat
,
error
)
{
sizeStat
,
err
:=
RepoSize
(
ctx
,
n
)
usage
,
err
:=
r
.
GetStorageUsage
()
if
err
!=
nil
{
if
err
!=
nil
{
return
nil
,
err
return
Stat
{}
,
err
}
}
allKeys
,
err
:=
n
.
Blockstore
.
AllKeysChan
(
ctx
)
allKeys
,
err
:=
n
.
Blockstore
.
AllKeysChan
(
ctx
)
if
err
!=
nil
{
if
err
!=
nil
{
return
nil
,
err
return
Stat
{}
,
err
}
}
count
:=
uint64
(
0
)
count
:=
uint64
(
0
)
...
@@ -42,27 +48,44 @@ func RepoStat(n *core.IpfsNode, ctx context.Context) (*Stat, error) {
...
@@ -42,27 +48,44 @@ func RepoStat(n *core.IpfsNode, ctx context.Context) (*Stat, error) {
path
,
err
:=
fsrepo
.
BestKnownPath
()
path
,
err
:=
fsrepo
.
BestKnownPath
()
if
err
!=
nil
{
if
err
!=
nil
{
return
nil
,
err
return
Stat
{}
,
err
}
}
return
Stat
{
SizeStat
:
SizeStat
{
RepoSize
:
sizeStat
.
RepoSize
,
StorageMax
:
sizeStat
.
StorageMax
,
},
NumObjects
:
count
,
RepoPath
:
path
,
Version
:
fmt
.
Sprintf
(
"fs-repo@%d"
,
fsrepo
.
RepoVersion
),
},
nil
}
// RepoSize returns a *Stat object with the RepoSize and StorageMax fields set.
func
RepoSize
(
ctx
context
.
Context
,
n
*
core
.
IpfsNode
)
(
SizeStat
,
error
)
{
r
:=
n
.
Repo
cfg
,
err
:=
r
.
Config
()
cfg
,
err
:=
r
.
Config
()
if
err
!=
nil
{
if
err
!=
nil
{
return
nil
,
err
return
SizeStat
{},
err
}
usage
,
err
:=
r
.
GetStorageUsage
()
if
err
!=
nil
{
return
SizeStat
{},
err
}
}
storageMax
:=
NoLimit
storageMax
:=
NoLimit
if
cfg
.
Datastore
.
StorageMax
!=
""
{
if
cfg
.
Datastore
.
StorageMax
!=
""
{
storageMax
,
err
=
humanize
.
ParseBytes
(
cfg
.
Datastore
.
StorageMax
)
storageMax
,
err
=
humanize
.
ParseBytes
(
cfg
.
Datastore
.
StorageMax
)
if
err
!=
nil
{
if
err
!=
nil
{
return
nil
,
err
return
SizeStat
{}
,
err
}
}
}
}
return
&
Stat
{
return
SizeStat
{
NumObjects
:
count
,
RepoSize
:
usage
,
RepoSize
:
usage
,
RepoPath
:
path
,
Version
:
fmt
.
Sprintf
(
"fs-repo@%d"
,
fsrepo
.
RepoVersion
),
StorageMax
:
storageMax
,
StorageMax
:
storageMax
,
},
nil
},
nil
}
}
repo/fsrepo/fsrepo.go
浏览文件 @
07feeec9
...
@@ -27,6 +27,7 @@ import (
...
@@ -27,6 +27,7 @@ import (
ma
"gx/ipfs/QmYmsdtJ3HsodkePE3eU3TsCaP2YvPZJ4LoXnNkDE5Tpt7/go-multiaddr"
ma
"gx/ipfs/QmYmsdtJ3HsodkePE3eU3TsCaP2YvPZJ4LoXnNkDE5Tpt7/go-multiaddr"
lockfile
"gx/ipfs/QmYzCZUe9CBDkyPNPcRNqXQK8KKhtUfXvc88PkFujAEJPe/go-fs-lock"
lockfile
"gx/ipfs/QmYzCZUe9CBDkyPNPcRNqXQK8KKhtUfXvc88PkFujAEJPe/go-fs-lock"
logging
"gx/ipfs/QmcVVHfdyv15GVPk7NrxdWjh2hLVccXnoD8j2tyQShiXJb/go-log"
logging
"gx/ipfs/QmcVVHfdyv15GVPk7NrxdWjh2hLVccXnoD8j2tyQShiXJb/go-log"
ds
"gx/ipfs/QmeiCcJfDW1GJnWUArudsv5rQsihpi4oyddPhdqo3CfX6i/go-datastore"
)
)
// LockFile is the filename of the repo lock, relative to config dir
// LockFile is the filename of the repo lock, relative to config dir
...
@@ -674,29 +675,7 @@ func (r *FSRepo) Datastore() repo.Datastore {
...
@@ -674,29 +675,7 @@ func (r *FSRepo) Datastore() repo.Datastore {
// GetStorageUsage computes the storage space taken by the repo in bytes
// GetStorageUsage computes the storage space taken by the repo in bytes
func
(
r
*
FSRepo
)
GetStorageUsage
()
(
uint64
,
error
)
{
func
(
r
*
FSRepo
)
GetStorageUsage
()
(
uint64
,
error
)
{
pth
,
err
:=
config
.
PathRoot
()
return
ds
.
DiskUsage
(
r
.
Datastore
())
if
err
!=
nil
{
return
0
,
err
}
pth
,
err
=
filepath
.
EvalSymlinks
(
pth
)
if
err
!=
nil
{
log
.
Debugf
(
"filepath.EvalSymlinks error: %s"
,
err
)
return
0
,
err
}
var
du
uint64
err
=
filepath
.
Walk
(
pth
,
func
(
p
string
,
f
os
.
FileInfo
,
err
error
)
error
{
if
err
!=
nil
{
log
.
Debugf
(
"filepath.Walk error: %s"
,
err
)
return
nil
}
if
f
!=
nil
{
du
+=
uint64
(
f
.
Size
())
}
return
nil
})
return
du
,
err
}
}
func
(
r
*
FSRepo
)
SwarmKey
()
([]
byte
,
error
)
{
func
(
r
*
FSRepo
)
SwarmKey
()
([]
byte
,
error
)
{
...
...
test/sharness/t0080-repo.sh
浏览文件 @
07feeec9
...
@@ -245,6 +245,18 @@ test_expect_success "repo stats are updated correctly" '
...
@@ -245,6 +245,18 @@ test_expect_success "repo stats are updated correctly" '
test $(get_field_num "RepoSize" repo-stats-2) -ge $(get_field_num "RepoSize" repo-stats)
test $(get_field_num "RepoSize" repo-stats-2) -ge $(get_field_num "RepoSize" repo-stats)
'
'
test_expect_success
"'ipfs repo stat --size-only' succeeds"
'
ipfs repo stat --size-only > repo-stats-size-only
'
test_expect_success
"repo stats came out correct for --size-only"
'
grep "RepoSize" repo-stats-size-only &&
grep "StorageMax" repo-stats-size-only &&
grep -v "RepoPath" repo-stats-size-only &&
grep -v "NumObjects" repo-stats-size-only &&
grep -v "Version" repo-stats-size-only
'
test_expect_success
"'ipfs repo version' succeeds"
'
test_expect_success
"'ipfs repo version' succeeds"
'
ipfs repo version > repo-version
ipfs repo version > repo-version
'
'
...
...
编写
预览
Markdown
格式
0%
重试
或
添加新文件
添加附件
取消
您添加了
0
人
到此讨论。请谨慎行事。
请先完成此评论的编辑!
取消
请
注册
或者
登录
后发表评论