Skip to content
GitLab
Projects
Groups
Snippets
Help
Loading...
Help
What's new
10
Help
Support
Community forum
Keyboard shortcuts
?
Submit feedback
Contribute to GitLab
Sign in
Toggle navigation
Open sidebar
dms3
go-ds-flatfs
Commits
53d4c9b1
Unverified
Commit
53d4c9b1
authored
Apr 10, 2020
by
Will
Committed by
GitHub
Apr 10, 2020
Browse files
Options
Browse Files
Download
Email Patches
Plain Diff
add fd-overload retries inline (#75)
add fd-overload retries inline
parent
01ce5da4
Changes
1
Hide whitespace changes
Inline
Side-by-side
Showing
1 changed file
with
80 additions
and
14 deletions
+80
-14
flatfs.go
flatfs.go
+80
-14
No files found.
flatfs.go
View file @
53d4c9b1
...
@@ -14,6 +14,7 @@ import (
...
@@ -14,6 +14,7 @@ import (
"strings"
"strings"
"sync"
"sync"
"sync/atomic"
"sync/atomic"
"syscall"
"time"
"time"
"github.com/ipfs/go-datastore"
"github.com/ipfs/go-datastore"
...
@@ -48,6 +49,9 @@ var (
...
@@ -48,6 +49,9 @@ var (
// If this period did not suffice to read the size of the datastore,
// If this period did not suffice to read the size of the datastore,
// the remaining sizes will be stimated.
// the remaining sizes will be stimated.
DiskUsageCalcTimeout = 5 * time.Minute
DiskUsageCalcTimeout = 5 * time.Minute
// RetryDelay is a timeout for a backoff on retrying operations
// that fail due to transient errors like too many file descriptors open.
RetryDelay = time.Millisecond * 200
)
)
const (
const (
...
@@ -432,6 +436,15 @@ func (fs *Datastore) doOp(oper *op) error {
...
@@ -432,6 +436,15 @@ func (fs *Datastore) doOp(oper *op) error {
}
}
}
}
func isTooManyFDError(err error) bool {
perr, ok := err.(*os.PathError)
if ok && perr.Err == syscall.EMFILE {
return true
}
return false
}
// doWrite optimizes out write operations (put/delete) to the same
// doWrite optimizes out write operations (put/delete) to the same
// key by queueing them and succeeding all queued
// key by queueing them and succeeding all queued
// operations if one of them does. In such case,
// operations if one of them does. In such case,
...
@@ -447,7 +460,15 @@ func (fs *Datastore) doWriteOp(oper *op) error {
...
@@ -447,7 +460,15 @@ func (fs *Datastore) doWriteOp(oper *op) error {
}
}
// Do the operation
// Do the operation
err
:=
fs
.
doOp
(
oper
)
var err error
for i := 0; i < 6; i++ {
err = fs.doOp(oper)
if err == nil || !isTooManyFDError(err) {
break
}
time.Sleep(time.Duration(i+1) * RetryDelay)
}
// Finish it. If no error, it will signal other operations
// Finish it. If no error, it will signal other operations
// waiting on this result to succeed. Otherwise, they will
// waiting on this result to succeed. Otherwise, they will
...
@@ -532,6 +553,28 @@ func (fs *Datastore) putMany(data map[datastore.Key][]byte) error {
...
@@ -532,6 +553,28 @@ func (fs *Datastore) putMany(data map[datastore.Key][]byte) error {
}
}
}()
}()
closer := func() error {
for fi := range files {
if ops[fi] != 0 {
continue
}
if fs.sync {
if err := syncFile(fi); err != nil {
return err
}
}
if err := fi.Close(); err != nil {
return err
}
// signify closed
ops[fi] = 1
}
return nil
}
for key, value := range data {
for key, value := range data {
dir, path := fs.encode(key)
dir, path := fs.encode(key)
if err := fs.makeDirNoSync(dir); err != nil {
if err := fs.makeDirNoSync(dir); err != nil {
...
@@ -540,6 +583,21 @@ func (fs *Datastore) putMany(data map[datastore.Key][]byte) error {
...
@@ -540,6 +583,21 @@ func (fs *Datastore) putMany(data map[datastore.Key][]byte) error {
dirsToSync = append(dirsToSync, dir)
dirsToSync = append(dirsToSync, dir)
tmp, err := fs.tempFile()
tmp, err := fs.tempFile()
// Fallback retry for temporary error.
if err != nil && isTooManyFDError(err) {
if err = closer(); err != nil {
return err
}
for i := 0; i < 6; i++ {
time.Sleep(time.Duration(i+1) * RetryDelay)
tmp, err = fs.tempFile()
if err == nil || !isTooManyFDError(err) {
break
}
}
}
if err != nil {
if err != nil {
return err
return err
}
}
...
@@ -558,19 +616,9 @@ func (fs *Datastore) putMany(data map[datastore.Key][]byte) error {
...
@@ -558,19 +616,9 @@ func (fs *Datastore) putMany(data map[datastore.Key][]byte) error {
// Now we sync everything
// Now we sync everything
// sync and close files
// sync and close files
for
fi
:=
range
files
{
err := closer()
if
fs
.
sync
{
if err != nil {
if
err
:=
syncFile
(
fi
);
err
!=
nil
{
return err
return
err
}
}
if
err
:=
fi
.
Close
();
err
!=
nil
{
return
err
}
// signify closed
ops
[
fi
]
=
1
}
}
// move files to their proper places
// move files to their proper places
...
@@ -601,6 +649,24 @@ func (fs *Datastore) putMany(data map[datastore.Key][]byte) error {
...
@@ -601,6 +649,24 @@ func (fs *Datastore) putMany(data map[datastore.Key][]byte) error {
}
}
func (fs *Datastore) Get(key datastore.Key) (value []byte, err error) {
func (fs *Datastore) Get(key datastore.Key) (value []byte, err error) {
value, err = fs.get(key)
// Fallback retry for temporary error.
if err != nil && isTooManyFDError(err) {
for i := 0; i < 6; i++ {
time.Sleep(time.Duration(i+1) * RetryDelay)
value, err = fs.get(key)
if err == nil || !isTooManyFDError(err) {
break
}
}
}
return
}
func (fs *Datastore) get(key datastore.Key) (value []byte, err error) {
// Can't exist in datastore.
// Can't exist in datastore.
if !keyIsValid(key) {
if !keyIsValid(key) {
return nil, datastore.ErrNotFound
return nil, datastore.ErrNotFound
...
...
Write
Preview
Markdown
is supported
0%
Try again
or
attach a new file
.
Attach a file
Cancel
You are about to add
0
people
to the discussion. Proceed with caution.
Finish editing this message first!
Cancel
Please
register
or
sign in
to comment