Skip to content
项目
群组
代码片段
帮助
当前项目
正在载入...
登录 / 注册
切换导航面板
G
go-ipfs
概览
概览
详情
活动
周期分析
版本库
仓库
文件
提交
分支
标签
贡献者
分支图
比较
统计图
问题
0
议题
0
列表
看板
标记
里程碑
合并请求
0
合并请求
0
CI / CD
CI / CD
流水线
作业
日程表
图表
维基
Wiki
代码片段
代码片段
成员
成员
折叠边栏
关闭边栏
活动
图像
聊天
创建新问题
作业
提交
问题看板
Open sidebar
jihao
go-ipfs
Commits
40e41d24
提交
40e41d24
authored
1月 13, 2015
作者:
Brian Tiger Chow
浏览文件
操作
浏览文件
下载
电子邮件补丁
差异文件
feat(fsrepo): protect with a repo lockfile
NB: daemon is one spot the repo lock is typically acquired
上级
67c161fb
隐藏空白字符变更
内嵌
并排
正在显示
5 个修改的文件
包含
60 行增加
和
16 行删除
+60
-16
daemon.go
cmd/ipfs/daemon.go
+5
-5
main.go
cmd/ipfs/main.go
+1
-2
fsrepo.go
repo/fsrepo/fsrepo.go
+48
-5
lock.go
repo/fsrepo/lock/lock.go
+2
-2
counter.go
repo/fsrepo/opener/counter.go
+4
-2
没有找到文件。
cmd/ipfs/daemon.go
浏览文件 @
40e41d24
...
...
@@ -12,7 +12,7 @@ import (
cmdsHttp
"github.com/jbenet/go-ipfs/commands/http"
core
"github.com/jbenet/go-ipfs/core"
commands
"github.com/jbenet/go-ipfs/core/commands"
daemon
"github.com/jbenet/go-ipfs/core/daemon
"
fsrepo
"github.com/jbenet/go-ipfs/repo/fsrepo
"
util
"github.com/jbenet/go-ipfs/util"
"github.com/jbenet/go-ipfs/util/debugerror"
)
...
...
@@ -89,13 +89,13 @@ func daemonFunc(req cmds.Request) (interface{}, error) {
return
nil
,
err
}
// acquire the
daemon
lock _before_ constructing a node. we need to make
// acquire the
repo
lock _before_ constructing a node. we need to make
// sure we are permitted to access the resources (datastore, etc.)
lock
,
err
:=
daemon
.
Lock
(
req
.
Context
()
.
ConfigRoot
)
if
err
!=
nil
{
repo
:=
fsrepo
.
At
(
req
.
Context
()
.
ConfigRoot
)
if
err
:=
repo
.
Open
();
err
!=
nil
{
return
nil
,
debugerror
.
Errorf
(
"Couldn't obtain lock. Is another daemon already running?"
)
}
defer
lock
.
Close
()
defer
repo
.
Close
()
// OK!!! Now we're ready to construct the node.
// make sure we construct an online node.
...
...
cmd/ipfs/main.go
浏览文件 @
40e41d24
...
...
@@ -20,7 +20,6 @@ import (
cmdsCli
"github.com/jbenet/go-ipfs/commands/cli"
cmdsHttp
"github.com/jbenet/go-ipfs/commands/http"
core
"github.com/jbenet/go-ipfs/core"
daemon
"github.com/jbenet/go-ipfs/core/daemon"
repo
"github.com/jbenet/go-ipfs/repo"
config
"github.com/jbenet/go-ipfs/repo/config"
fsrepo
"github.com/jbenet/go-ipfs/repo/fsrepo"
...
...
@@ -392,7 +391,7 @@ func commandShouldRunOnDaemon(details cmdDetails, req cmds.Request, root *cmds.C
// at this point need to know whether daemon is running. we defer
// to this point so that some commands dont open files unnecessarily.
daemonLocked
:=
daemon
.
Locked
(
req
.
Context
()
.
ConfigRoot
)
daemonLocked
:=
fsrepo
.
LockedByOtherProcess
(
req
.
Context
()
.
ConfigRoot
)
if
daemonLocked
{
...
...
repo/fsrepo/fsrepo.go
浏览文件 @
40e41d24
...
...
@@ -10,6 +10,7 @@ import (
repo
"github.com/jbenet/go-ipfs/repo"
common
"github.com/jbenet/go-ipfs/repo/common"
config
"github.com/jbenet/go-ipfs/repo/config"
lockfile
"github.com/jbenet/go-ipfs/repo/fsrepo/lock"
opener
"github.com/jbenet/go-ipfs/repo/fsrepo/opener"
util
"github.com/jbenet/go-ipfs/util"
debugerror
"github.com/jbenet/go-ipfs/util/debugerror"
...
...
@@ -24,10 +25,13 @@ var (
// If an operation is used when repo is Open and the operation does not
// change the repo's state, the package lock does not need to be acquired.
openerCounter
*
opener
.
Counter
lockfiles
map
[
string
]
io
.
Closer
)
func
init
()
{
openerCounter
=
opener
.
NewCounter
()
lockfiles
=
make
(
map
[
string
]
io
.
Closer
)
}
// FSRepo represents an IPFS FileSystem Repo. It is not thread-safe.
...
...
@@ -74,6 +78,15 @@ func Remove(path string) error {
return
os
.
RemoveAll
(
path
)
}
// LockedByOtherProcess returns true if the FSRepo is locked by another
// process. If true, then the repo cannot be opened by this process.
func
LockedByOtherProcess
(
repoPath
string
)
bool
{
openerCounter
.
Lock
()
defer
openerCounter
.
Unlock
()
// NB: the lock is only held when repos are Open
return
lockfile
.
Locked
(
repoPath
)
&&
openerCounter
.
NumOpeners
(
repoPath
)
==
0
}
// Open returns an error if the repo is not initialized.
func
(
r
*
FSRepo
)
Open
()
error
{
openerCounter
.
Lock
()
...
...
@@ -118,9 +131,7 @@ func (r *FSRepo) Open() error {
return
debugerror
.
Errorf
(
"logs: %s"
,
err
)
}
r
.
state
=
opened
openerCounter
.
AddOpener
(
r
.
path
)
return
nil
return
transitionToOpened
(
r
)
}
// Config returns the FSRepo's config. This method must not be called if the
...
...
@@ -217,8 +228,7 @@ func (r *FSRepo) Close() error {
if
r
.
state
!=
opened
{
return
debugerror
.
Errorf
(
"repo is %s"
,
r
.
state
)
}
openerCounter
.
RemoveOpener
(
r
.
path
)
return
nil
// TODO release repo lock
return
transitionToClosed
(
r
)
}
var
_
io
.
Closer
=
&
FSRepo
{}
...
...
@@ -258,3 +268,36 @@ func initCheckDir(path string) error {
}
return
nil
}
// transitionToOpened manages the state transition to |opened|. Caller must hold
// openerCounter lock.
func
transitionToOpened
(
r
*
FSRepo
)
error
{
r
.
state
=
opened
if
countBefore
:=
openerCounter
.
NumOpeners
(
r
.
path
);
countBefore
==
0
{
// #first
closer
,
err
:=
lockfile
.
Lock
(
r
.
path
)
if
err
!=
nil
{
return
err
}
lockfiles
[
r
.
path
]
=
closer
}
return
openerCounter
.
AddOpener
(
r
.
path
)
}
// transitionToClosed manages the state transition to |closed|. Caller must
// hold openerCounter lock.
func
transitionToClosed
(
r
*
FSRepo
)
error
{
r
.
state
=
closed
if
err
:=
openerCounter
.
RemoveOpener
(
r
.
path
);
err
!=
nil
{
return
err
}
if
countAfter
:=
openerCounter
.
NumOpeners
(
r
.
path
);
countAfter
==
0
{
closer
,
ok
:=
lockfiles
[
r
.
path
]
if
!
ok
{
return
errors
.
New
(
"package error: lockfile is not held"
)
}
if
err
:=
closer
.
Close
();
err
!=
nil
{
return
err
}
}
return
nil
}
core/daemon/daemon
.go
→
repo/fsrepo/lock/lock
.go
浏览文件 @
40e41d24
package
daemon
package
lock
import
(
"io"
...
...
@@ -10,6 +10,7 @@ import (
)
// LockFile is the filename of the daemon lock, relative to config dir
// TODO rename repo lock and hide name
const
LockFile
=
"daemon.lock"
func
Lock
(
confdir
string
)
(
io
.
Closer
,
error
)
{
...
...
@@ -23,7 +24,6 @@ func Locked(confdir string) bool {
}
if
lk
,
err
:=
Lock
(
confdir
);
err
!=
nil
{
return
true
}
else
{
lk
.
Close
()
return
false
...
...
repo/fsrepo/opener/counter.go
浏览文件 @
40e41d24
...
...
@@ -38,15 +38,17 @@ func (l *Counter) NumOpeners(repoPath string) int {
// AddOpener messages that an FSRepo holds a handle to the repo at this path.
// This method is not thread-safe. The caller must have this object locked.
func
(
l
*
Counter
)
AddOpener
(
repoPath
string
)
{
func
(
l
*
Counter
)
AddOpener
(
repoPath
string
)
error
{
l
.
repos
[
key
(
repoPath
)]
++
return
nil
}
// RemoveOpener messgaes that an FSRepo no longer holds a handle to the repo at
// this path. This method is not thread-safe. The caller must have this object
// locked.
func
(
l
*
Counter
)
RemoveOpener
(
repoPath
string
)
{
func
(
l
*
Counter
)
RemoveOpener
(
repoPath
string
)
error
{
l
.
repos
[
key
(
repoPath
)]
--
return
nil
}
func
key
(
repoPath
string
)
string
{
...
...
编写
预览
Markdown
格式
0%
重试
或
添加新文件
添加附件
取消
您添加了
0
人
到此讨论。请谨慎行事。
请先完成此评论的编辑!
取消
请
注册
或者
登录
后发表评论