Skip to content
体验新版
项目
组织
正在加载...
登录
切换导航
打开侧边栏
whqwjb
go-ethereum
提交
6810674d
G
go-ethereum
项目概览
whqwjb
/
go-ethereum
与 Fork 源项目一致
从无法访问的项目Fork
通知
1
Star
0
Fork
0
代码
文件
提交
分支
Tags
贡献者
分支图
Diff
Issue
0
列表
看板
标记
里程碑
合并请求
0
Wiki
0
Wiki
分析
仓库
DevOps
项目成员
Pages
G
go-ethereum
项目概览
项目概览
详情
发布
仓库
仓库
文件
提交
分支
标签
贡献者
分支图
比较
Issue
0
Issue
0
列表
看板
标记
里程碑
合并请求
0
合并请求
0
Pages
分析
分析
仓库分析
DevOps
Wiki
0
Wiki
成员
成员
收起侧边栏
关闭侧边栏
动态
分支图
创建新Issue
提交
Issue看板
体验新版 GitCode,发现更多精彩内容 >>
未验证
提交
6810674d
编写于
11月 20, 2017
作者:
P
Péter Szilágyi
浏览文件
操作
浏览文件
下载
电子邮件补丁
差异文件
accounts/keystore: lock file cache during scan, minor polish
上级
8a798360
变更
2
显示空白变更内容
内联
并排
Showing
2 changed file
with
124 addition
and
91 deletion
+124
-91
accounts/keystore/account_cache.go
accounts/keystore/account_cache.go
+22
-91
accounts/keystore/file_cache.go
accounts/keystore/file_cache.go
+102
-0
未找到文件。
accounts/keystore/account_cache.go
浏览文件 @
6810674d
...
...
@@ -20,7 +20,6 @@ import (
"bufio"
"encoding/json"
"fmt"
"io/ioutil"
"os"
"path/filepath"
"sort"
...
...
@@ -75,13 +74,6 @@ type accountCache struct {
fileC
fileCache
}
// fileCache is a cache of files seen during scan of keystore
type
fileCache
struct
{
all
*
set
.
SetNonTS
// list of all files
mtime
time
.
Time
// latest mtime seen
mu
sync
.
RWMutex
}
func
newAccountCache
(
keydir
string
)
(
*
accountCache
,
chan
struct
{})
{
ac
:=
&
accountCache
{
keydir
:
keydir
,
...
...
@@ -236,66 +228,22 @@ func (ac *accountCache) close() {
ac
.
mu
.
Unlock
()
}
// scanFiles performs a new scan on the given directory, compares against the already
// cached filenames, and returns file sets: new, missing , modified
func
(
fc
*
fileCache
)
scanFiles
(
keyDir
string
)
(
set
.
Interface
,
set
.
Interface
,
set
.
Interface
,
error
)
{
t0
:=
time
.
Now
()
files
,
err
:=
ioutil
.
ReadDir
(
keyDir
)
t1
:=
time
.
Now
()
if
err
!=
nil
{
return
nil
,
nil
,
nil
,
err
}
fc
.
mu
.
RLock
()
prevMtime
:=
fc
.
mtime
fc
.
mu
.
RUnlock
()
filesNow
:=
set
.
NewNonTS
()
moddedFiles
:=
set
.
NewNonTS
()
var
newMtime
time
.
Time
for
_
,
fi
:=
range
files
{
modTime
:=
fi
.
ModTime
()
path
:=
filepath
.
Join
(
keyDir
,
fi
.
Name
())
if
skipKeyFile
(
fi
)
{
log
.
Trace
(
"Ignoring file on account scan"
,
"path"
,
path
)
continue
}
filesNow
.
Add
(
path
)
if
modTime
.
After
(
prevMtime
)
{
moddedFiles
.
Add
(
path
)
}
if
modTime
.
After
(
newMtime
)
{
newMtime
=
modTime
}
}
t2
:=
time
.
Now
()
fc
.
mu
.
Lock
()
// Missing = previous - current
missing
:=
set
.
Difference
(
fc
.
all
,
filesNow
)
// New = current - previous
newFiles
:=
set
.
Difference
(
filesNow
,
fc
.
all
)
// Modified = modified - new
modified
:=
set
.
Difference
(
moddedFiles
,
newFiles
)
fc
.
all
=
filesNow
fc
.
mtime
=
newMtime
fc
.
mu
.
Unlock
()
t3
:=
time
.
Now
()
log
.
Debug
(
"FS scan times"
,
"list"
,
t1
.
Sub
(
t0
),
"set"
,
t2
.
Sub
(
t1
),
"diff"
,
t3
.
Sub
(
t2
))
return
newFiles
,
missing
,
modified
,
nil
}
// scanAccounts checks if any changes have occurred on the filesystem, and
// updates the account cache accordingly
func
(
ac
*
accountCache
)
scanAccounts
()
error
{
newFiles
,
missingFiles
,
modified
,
err
:=
ac
.
fileC
.
scanFiles
(
ac
.
keydir
)
t1
:=
time
.
Now
(
)
// Scan the entire folder metadata for file changes
creates
,
deletes
,
updates
,
err
:=
ac
.
fileC
.
scan
(
ac
.
keydir
)
if
err
!=
nil
{
log
.
Debug
(
"Failed to reload keystore contents"
,
"err"
,
err
)
return
err
}
if
creates
.
Size
()
==
0
&&
deletes
.
Size
()
==
0
&&
updates
.
Size
()
==
0
{
return
nil
}
// Create a helper method to scan the contents of the key files
var
(
buf
=
new
(
bufio
.
Reader
)
key
JSON
struct
{
key
struct
{
Address
string
`json:"address"`
}
)
...
...
@@ -308,9 +256,9 @@ func (ac *accountCache) scanAccounts() error {
defer
fd
.
Close
()
buf
.
Reset
(
fd
)
// Parse the address.
key
JSON
.
Address
=
""
err
=
json
.
NewDecoder
(
buf
)
.
Decode
(
&
key
JSON
)
addr
:=
common
.
HexToAddress
(
key
JSON
.
Address
)
key
.
Address
=
""
err
=
json
.
NewDecoder
(
buf
)
.
Decode
(
&
key
)
addr
:=
common
.
HexToAddress
(
key
.
Address
)
switch
{
case
err
!=
nil
:
log
.
Debug
(
"Failed to decode keystore key"
,
"path"
,
path
,
"err"
,
err
)
...
...
@@ -321,47 +269,30 @@ func (ac *accountCache) scanAccounts() error {
}
return
nil
}
// Process all the file diffs
start
:=
time
.
Now
()
for
_
,
p
:=
range
newFiles
.
List
()
{
path
,
_
:=
p
.
(
string
)
a
:=
readAccount
(
path
)
if
a
!=
nil
{
for
_
,
p
:=
range
creates
.
List
()
{
if
a
:=
readAccount
(
p
.
(
string
));
a
!=
nil
{
ac
.
add
(
*
a
)
}
}
for
_
,
p
:=
range
missingFiles
.
List
()
{
path
,
_
:=
p
.
(
string
)
ac
.
deleteByFile
(
path
)
for
_
,
p
:=
range
deletes
.
List
()
{
ac
.
deleteByFile
(
p
.
(
string
))
}
for
_
,
p
:=
range
modified
.
List
()
{
path
,
_
:=
p
.
(
string
)
a
:=
readAccount
(
path
)
for
_
,
p
:=
range
updates
.
List
()
{
path
:=
p
.
(
string
)
ac
.
deleteByFile
(
path
)
if
a
!=
nil
{
if
a
:=
readAccount
(
path
);
a
!=
nil
{
ac
.
add
(
*
a
)
}
}
t2
:=
time
.
Now
()
end
:=
time
.
Now
()
select
{
case
ac
.
notify
<-
struct
{}{}
:
default
:
}
log
.
Trace
(
"Handled keystore changes"
,
"time"
,
t2
.
Sub
(
t1
))
log
.
Trace
(
"Handled keystore changes"
,
"time"
,
end
.
Sub
(
start
))
return
nil
}
func
skipKeyFile
(
fi
os
.
FileInfo
)
bool
{
// Skip editor backups and UNIX-style hidden files.
if
strings
.
HasSuffix
(
fi
.
Name
(),
"~"
)
||
strings
.
HasPrefix
(
fi
.
Name
(),
"."
)
{
return
true
}
// Skip misc special files, directories (yes, symlinks too).
if
fi
.
IsDir
()
||
fi
.
Mode
()
&
os
.
ModeType
!=
0
{
return
true
}
return
false
}
accounts/keystore/file_cache.go
0 → 100644
浏览文件 @
6810674d
// Copyright 2017 The go-ethereum Authors
// This file is part of the go-ethereum library.
//
// The go-ethereum library is free software: you can redistribute it and/or modify
// it under the terms of the GNU Lesser General Public License as published by
// the Free Software Foundation, either version 3 of the License, or
// (at your option) any later version.
//
// The go-ethereum library is distributed in the hope that it will be useful,
// but WITHOUT ANY WARRANTY; without even the implied warranty of
// MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
// GNU Lesser General Public License for more details.
//
// You should have received a copy of the GNU Lesser General Public License
// along with the go-ethereum library. If not, see <http://www.gnu.org/licenses/>.
package
keystore
import
(
"io/ioutil"
"os"
"path/filepath"
"strings"
"sync"
"time"
"github.com/ethereum/go-ethereum/log"
set
"gopkg.in/fatih/set.v0"
)
// fileCache is a cache of files seen during scan of keystore.
type
fileCache
struct
{
all
*
set
.
SetNonTS
// Set of all files from the keystore folder
lastMod
time
.
Time
// Last time instance when a file was modified
mu
sync
.
RWMutex
}
// scan performs a new scan on the given directory, compares against the already
// cached filenames, and returns file sets: creates, deletes, updates.
func
(
fc
*
fileCache
)
scan
(
keyDir
string
)
(
set
.
Interface
,
set
.
Interface
,
set
.
Interface
,
error
)
{
t0
:=
time
.
Now
()
// List all the failes from the keystore folder
files
,
err
:=
ioutil
.
ReadDir
(
keyDir
)
if
err
!=
nil
{
return
nil
,
nil
,
nil
,
err
}
t1
:=
time
.
Now
()
fc
.
mu
.
Lock
()
defer
fc
.
mu
.
Unlock
()
// Iterate all the files and gather their metadata
all
:=
set
.
NewNonTS
()
mods
:=
set
.
NewNonTS
()
var
newLastMod
time
.
Time
for
_
,
fi
:=
range
files
{
// Skip any non-key files from the folder
path
:=
filepath
.
Join
(
keyDir
,
fi
.
Name
())
if
skipKeyFile
(
fi
)
{
log
.
Trace
(
"Ignoring file on account scan"
,
"path"
,
path
)
continue
}
// Gather the set of all and fresly modified files
all
.
Add
(
path
)
modified
:=
fi
.
ModTime
()
if
modified
.
After
(
fc
.
lastMod
)
{
mods
.
Add
(
path
)
}
if
modified
.
After
(
newLastMod
)
{
newLastMod
=
modified
}
}
t2
:=
time
.
Now
()
// Update the tracked files and return the three sets
deletes
:=
set
.
Difference
(
fc
.
all
,
all
)
// Deletes = previous - current
creates
:=
set
.
Difference
(
all
,
fc
.
all
)
// Creates = current - previous
updates
:=
set
.
Difference
(
mods
,
creates
)
// Updates = modified - creates
fc
.
all
,
fc
.
lastMod
=
all
,
newLastMod
t3
:=
time
.
Now
()
// Report on the scanning stats and return
log
.
Debug
(
"FS scan times"
,
"list"
,
t1
.
Sub
(
t0
),
"set"
,
t2
.
Sub
(
t1
),
"diff"
,
t3
.
Sub
(
t2
))
return
creates
,
deletes
,
updates
,
nil
}
// skipKeyFile ignores editor backups, hidden files and folders/symlinks.
func
skipKeyFile
(
fi
os
.
FileInfo
)
bool
{
// Skip editor backups and UNIX-style hidden files.
if
strings
.
HasSuffix
(
fi
.
Name
(),
"~"
)
||
strings
.
HasPrefix
(
fi
.
Name
(),
"."
)
{
return
true
}
// Skip misc special files, directories (yes, symlinks too).
if
fi
.
IsDir
()
||
fi
.
Mode
()
&
os
.
ModeType
!=
0
{
return
true
}
return
false
}
编辑
预览
Markdown
is supported
0%
请重试
或
添加新附件
.
添加附件
取消
You are about to add
0
people
to the discussion. Proceed with caution.
先完成此消息的编辑!
取消
想要评论请
注册
或
登录