Synchronize virtfs rdwr state
This commit is contained in:
parent
c0ce185051
commit
562e1ef780
|
|
@ -5,6 +5,7 @@ import (
|
||||||
"fmt"
|
"fmt"
|
||||||
"os"
|
"os"
|
||||||
"strings"
|
"strings"
|
||||||
|
"sync"
|
||||||
)
|
)
|
||||||
|
|
||||||
// BuildTree walks an FsNodeDecl spec and produces a *Tree.
|
// BuildTree walks an FsNodeDecl spec and produces a *Tree.
|
||||||
|
|
@ -257,31 +258,48 @@ func openLeaf(d *FsNodeDecl, uid, gid string, mode os.FileMode, name string) (Fi
|
||||||
isStreaming = true
|
isStreaming = true
|
||||||
case d.Rdwr != nil:
|
case d.Rdwr != nil:
|
||||||
fn := d.Rdwr
|
fn := d.Rdwr
|
||||||
|
var stateMu sync.Mutex
|
||||||
|
var writeMu sync.Mutex
|
||||||
var result []byte
|
var result []byte
|
||||||
var reqCtx context.Context
|
|
||||||
var reqCancel context.CancelFunc
|
var reqCancel context.CancelFunc
|
||||||
blockFn = notBlocking
|
blockFn = notBlocking
|
||||||
readFn = func() ([]byte, error) {
|
readFn = func() ([]byte, error) {
|
||||||
|
stateMu.Lock()
|
||||||
if result != nil {
|
if result != nil {
|
||||||
return result, nil
|
out := make([]byte, len(result))
|
||||||
|
copy(out, result)
|
||||||
|
stateMu.Unlock()
|
||||||
|
return out, nil
|
||||||
}
|
}
|
||||||
|
stateMu.Unlock()
|
||||||
if d.Read != nil {
|
if d.Read != nil {
|
||||||
return d.Read()
|
return d.Read()
|
||||||
}
|
}
|
||||||
return nil, nil
|
return nil, nil
|
||||||
}
|
}
|
||||||
writeFn = func(data []byte) error {
|
writeFn = func(data []byte) error {
|
||||||
reqCtx, reqCancel = context.WithCancel(context.Background())
|
writeMu.Lock()
|
||||||
r, err := fn(reqCtx, data)
|
defer writeMu.Unlock()
|
||||||
if err != nil {
|
ctx, cancel := context.WithCancel(context.Background())
|
||||||
return err
|
stateMu.Lock()
|
||||||
|
reqCancel = cancel
|
||||||
|
stateMu.Unlock()
|
||||||
|
r, err := fn(ctx, data)
|
||||||
|
stateMu.Lock()
|
||||||
|
reqCancel = nil
|
||||||
|
if err == nil {
|
||||||
|
result = append(result[:0], r...)
|
||||||
}
|
}
|
||||||
result = r
|
stateMu.Unlock()
|
||||||
return nil
|
cancel()
|
||||||
|
return err
|
||||||
}
|
}
|
||||||
closeFn := func() error {
|
closeFn := func() error {
|
||||||
if reqCancel != nil {
|
stateMu.Lock()
|
||||||
reqCancel()
|
cancel := reqCancel
|
||||||
|
stateMu.Unlock()
|
||||||
|
if cancel != nil {
|
||||||
|
cancel()
|
||||||
}
|
}
|
||||||
return nil
|
return nil
|
||||||
}
|
}
|
||||||
|
|
|
||||||
Loading…
Reference in New Issue