Skip to content
Projects
Groups
Snippets
Help
Loading...
Help
Support
Keyboard shortcuts
?
Submit feedback
Contribute to GitLab
Sign in / Register
Toggle navigation
W
wendelin.core
Project overview
Project overview
Details
Activity
Releases
Repository
Repository
Files
Commits
Branches
Tags
Contributors
Graph
Compare
Labels
Merge Requests
0
Merge Requests
0
Analytics
Analytics
Repository
Value Stream
Members
Members
Collapse sidebar
Close sidebar
Activity
Graph
Commits
Open sidebar
Kirill Smelkov
wendelin.core
Commits
5d775923
Commit
5d775923
authored
Dec 25, 2018
by
Kirill Smelkov
Browse files
Options
Browse Files
Download
Email Patches
Plain Diff
.
parent
bf88c4f5
Changes
1
Hide whitespace changes
Inline
Side-by-side
Showing
1 changed file
with
113 additions
and
162 deletions
+113
-162
wcfs/wcfs.go
wcfs/wcfs.go
+113
-162
No files found.
wcfs/wcfs.go
View file @
5d775923
...
@@ -364,14 +364,15 @@ package main
...
@@ -364,14 +364,15 @@ package main
// and a client that wants @rev data will get @rev data, even if it was this
// and a client that wants @rev data will get @rev data, even if it was this
// "old" client that triggered the pagefault(~).
// "old" client that triggered the pagefault(~).
//
//
// XXX 8) serving read from @<rev>/data + zconn(s) for historical state
//
//
// (*) see notes.txt -> "Notes on OS pagecache control"
// (*) see notes.txt -> "Notes on OS pagecache control"
// (+) see notes.txt -> "Invalidations to wcfs clients are delayed until block access"
// (+) see notes.txt -> "Invalidations to wcfs clients are delayed until block access"
// (~) see notes.txt -> "Changing mmapping while under pagefault is possible"
// (~) see notes.txt -> "Changing mmapping while under pagefault is possible"
// (^) see notes.txt -> "Client cannot be ptraced while under pagefault"
// (^) see notes.txt -> "Client cannot be ptraced while under pagefault"
// (%) no need to keep track of ZData - ZBlk1 is always marked as changed on blk data change.
// (%) no need to keep track of ZData - ZBlk1 is always marked as changed on blk data change.
//
//
// XXX 8) serving read from @<rev>/data + zconn(s) for historical state
//
// XXX For every ZODB connection a dedicated read-only transaction is maintained.
// XXX For every ZODB connection a dedicated read-only transaction is maintained.
import
(
import
(
...
@@ -418,37 +419,39 @@ type Root struct {
...
@@ -418,37 +419,39 @@ type Root struct {
// ZODB connections for @<rev>/
// ZODB connections for @<rev>/
zrevMu
sync
.
Mutex
zrevMu
sync
.
Mutex
zrevTab
map
[
zodb
.
Tid
]
*
ZConn
zrevTab
map
[
zodb
.
Tid
]
*
ZConn
// XXX include?
// // {} rev -> @<rev>/
// mu sync.Mutex
// revTab map[zodb.Tid]*Rev
}
}
// /
bigfile/ - served by BigFileRoot.
// /
(head|<rev>)/ - served by Head. XXX separate Rev?
type
BigFileRoot
struct
{
type
Head
struct
{
nodefs
.
Node
nodefs
.
Node
// bigfile, at, watch, etc - all implicitly linked to by fs
// {} oid -> <bigfileX>/
mu
sync
.
Mutex
tab
map
[
zodb
.
Oid
]
*
BigFileDir
}
}
// /
bigfile/<bigfileX>/ - served by BigFileDir
.
// /
head/watch - served by Watch
.
type
BigFileDir
struct
{
type
Watch
struct
{
nodefs
.
Node
nodefs
.
Node
oid
zodb
.
Oid
// oid of ZBigFile
// head/ is implicitly linked to by fs
// {} rev -> @<rev>/ bigfile snapshot
// TODO
mu
sync
.
Mutex
revTab
map
[
zodb
.
Tid
]
*
BigFileRev
}
}
// /
bigfile/<bigfileX>/(head|<rev>)/ - served by BigFileRev
.
// /
(head|<rev>)/bigfile/ - served by BigFileDir
.
type
BigFile
Rev
struct
{
type
BigFile
Dir
struct
{
nodefs
.
Node
nodefs
.
Node
// data, at, invalidations, etc - all implicitly linked to by fs
// {} oid -> <bigfileX>
mu
sync
.
Mutex
tab
map
[
zodb
.
Oid
]
*
BigFile
}
}
// /
bigfile/<bigfileX>/(head|<rev>)/* - internally
served by BigFile.
// /
(head|<rev>)/bigfile/<bigfileX> -
served by BigFile.
type
BigFile
struct
{
type
BigFile
struct
{
nodefs
.
Node
// this BigFile views ZODB via zconn
// this BigFile views ZODB via zconn
zconn
*
ZConn
zconn
*
ZConn
...
@@ -463,18 +466,9 @@ type BigFile struct {
...
@@ -463,18 +466,9 @@ type BigFile struct {
// TODO -> δFtail
// TODO -> δFtail
// lastChange zodb.Tid // last change to whole bigfile as of .zconn.At view
// lastChange zodb.Tid // last change to whole bigfile as of .zconn.At view
}
// /bigfile/<bigfileX>/(head|<rev>)/data - served by BigFileData.
type
BigFileData
struct
{
nodefs
.
Node
bigfile
*
BigFile
// inflight loadings of ZBigFile from ZODB.
// inflight loadings of ZBigFile from ZODB.
// successfull load results are kept here until blkdata is put into OS pagecache.
// successfull load results are kept here until blkdata is put into OS pagecache.
//
// XXX -> BigFile ?
loadMu
sync
.
Mutex
loadMu
sync
.
Mutex
loading
map
[
int64
]
*
blkLoadState
// #blk -> {... blkdata}
loading
map
[
int64
]
*
blkLoadState
// #blk -> {... blkdata}
...
@@ -524,6 +518,7 @@ func (cc *zodbCacheControl) WantEvict(obj zodb.IPersistent) bool {
...
@@ -524,6 +518,7 @@ func (cc *zodbCacheControl) WantEvict(obj zodb.IPersistent) bool {
return
false
return
false
}
}
/*
// zwatcher watches for ZODB changes.
// zwatcher watches for ZODB changes.
// see "4) when we receive an invalidation message from ZODB ..."
// see "4) when we receive an invalidation message from ZODB ..."
func (r *Root) zwatcher(ctx context.Context) (err error) {
func (r *Root) zwatcher(ctx context.Context) (err error) {
...
@@ -550,7 +545,7 @@ func (r *Root) zhandle1(zevent zodb.WatchEvent) {
...
@@ -550,7 +545,7 @@ func (r *Root) zhandle1(zevent zodb.WatchEvent) {
defer r.zheadMu.Unlock()
defer r.zheadMu.Unlock()
//toinvalidate := map[*ZBigFile]SetI64{} // {} zfile -> set(#blk)
//toinvalidate := map[*ZBigFile]SetI64{} // {} zfile -> set(#blk)
toinvalidate
:=
map
[
*
BigFile
Data
]
SetI64
{}
// {} zfile -> set(#blk)
toinvalidate := map[*BigFile]SetI64{} // {} zfile -> set(#blk)
// zevent = (tid^, []oid)
// zevent = (tid^, []oid)
for _, oid := range zevent.Changev {
for _, oid := range zevent.Changev {
...
@@ -601,7 +596,7 @@ func (r *Root) zhandle1(zevent zodb.WatchEvent) {
...
@@ -601,7 +596,7 @@ func (r *Root) zhandle1(zevent zodb.WatchEvent) {
// invalidateBlk invalidates 1 file block. XXX
// invalidateBlk invalidates 1 file block. XXX
// XXX see "4.4) for all file/blk to in invalidate we do"
// XXX see "4.4) for all file/blk to in invalidate we do"
func
(
f
*
BigFile
Data
)
invalidateBlk
(
ctx
context
.
Context
,
blk
int64
)
error
{
func (f *BigFile) invalidateBlk(ctx context.Context, blk int64) error {
fsconn := f.root().fsconn
fsconn := f.root().fsconn
off := blk*blksize
off := blk*blksize
...
@@ -630,20 +625,19 @@ func (f *BigFileData) invalidateBlk(ctx context.Context, blk int64) error {
...
@@ -630,20 +625,19 @@ func (f *BigFileData) invalidateBlk(ctx context.Context, blk int64) error {
panic("TODO")
panic("TODO")
}
}
*/
// ----------------------------------------
// ----------------------------------------
// /bigfile -> Mkdir receives client request to create /bigfile/<bigfileX>.
// /(head/<rev>)/bigfile/ -> Lookup receives client request to create (head|<rev>)/bigfile/<bigfileX>.
//
func
(
bfdir
*
BigFileDir
)
Lookup
(
out
*
fuse
.
Attr
,
name
string
,
fctx
*
fuse
.
Context
)
(
*
nodefs
.
Inode
,
fuse
.
Status
)
{
// It creates <bigfileX>/head/* along the way.
inode
,
err
:=
bfdir
.
lookup
(
out
,
name
,
fctx
)
// XXX reorder out?
func
(
bfroot
*
BigFileRoot
)
Mkdir
(
name
string
,
mode
uint32
,
fctx
*
fuse
.
Context
)
(
*
nodefs
.
Inode
,
fuse
.
Status
)
{
inode
,
err
:=
bfroot
.
mkdir
(
name
,
fctx
)
// XXX ok to ignore mode?
return
inode
,
err2LogStatus
(
err
)
return
inode
,
err2LogStatus
(
err
)
}
}
func
(
bf
root
*
BigFileRoot
)
mkdir
(
name
string
,
fctx
*
fuse
.
Context
)
(
_
*
nodefs
.
Inode
,
err
error
)
{
func
(
bf
dir
*
BigFileDir
)
lookup
(
out
*
fuse
.
Attr
,
name
string
,
fctx
*
fuse
.
Context
)
(
_
*
nodefs
.
Inode
,
err
error
)
{
defer
xerr
.
Contextf
(
&
err
,
"/bigfile:
mkdir
%q"
,
name
)
defer
xerr
.
Contextf
(
&
err
,
"/bigfile:
lookup
%q"
,
name
)
oid
,
err
:=
zodb
.
ParseOid
(
name
)
oid
,
err
:=
zodb
.
ParseOid
(
name
)
if
err
!=
nil
{
if
err
!=
nil
{
...
@@ -651,139 +645,100 @@ func (bfroot *BigFileRoot) mkdir(name string, fctx *fuse.Context) (_ *nodefs.Ino
...
@@ -651,139 +645,100 @@ func (bfroot *BigFileRoot) mkdir(name string, fctx *fuse.Context) (_ *nodefs.Ino
}
}
// check to see if dir(oid) is already there
// check to see if dir(oid) is already there
bf
root
.
mu
.
Lock
()
bf
dir
.
mu
.
Lock
()
_
,
already
:=
bfroot
.
tab
[
oid
]
f
,
already
:=
bfdir
.
tab
[
oid
]
bf
root
.
mu
.
Unlock
()
bf
dir
.
mu
.
Unlock
()
if
already
{
if
already
{
return
nil
,
syscall
.
EEXIST
// XXX fill out
return
f
.
Inode
(),
nil
}
}
// not there - without bf
root
lock proceed to open BigFile from ZODB
// not there - without bf
dir
lock proceed to open BigFile from ZODB
bf
,
err
:=
bigopen
(
asctx
(
fctx
),
groot
.
zhead
,
oid
)
f
,
err
=
bigopen
(
asctx
(
fctx
),
groot
.
zhead
,
oid
)
// XXX zhead -> head|rev.zconn
if
err
!=
nil
{
if
err
!=
nil
{
return
nil
,
err
return
nil
,
err
}
}
defer
func
()
{
if
err
!=
nil
{
bf
.
Close
()
}
}()
// relock bf
root and either mkdir or EEXIST if the directory
was maybe
// relock bf
dir and either register f or, if the file
was maybe
// simultanously created while we were not holding bf
root.mu
// simultanously created while we were not holding bf
dir.mu, return that.
bf
root
.
mu
.
Lock
()
bf
dir
.
mu
.
Lock
()
_
,
already
=
bfroot
.
tab
[
oid
]
f2
,
already
:=
bfdir
.
tab
[
oid
]
if
already
{
if
already
{
bfroot
.
mu
.
Unlock
()
bfdir
.
mu
.
Unlock
()
return
nil
,
syscall
.
EEXIST
f
.
Close
()
}
return
f2
.
Inode
(),
nil
// XXX fill out
bfdir
:=
&
BigFileDir
{
Node
:
nodefs
.
NewDefaultNode
(),
oid
:
oid
,
revTab
:
make
(
map
[
zodb
.
Tid
]
*
BigFileRev
),
}
bfhead
:=
&
BigFileRev
{
Node
:
nodefs
.
NewDefaultNode
(),
}
bfdata
:=
&
BigFileData
{
Node
:
nodefs
.
NewDefaultNode
(),
bigfile
:
bf
,
loading
:
make
(
map
[
int64
]
*
blkLoadState
),
}
}
bf
root
.
tab
[
oid
]
=
bfdir
bf
dir
.
tab
[
oid
]
=
f
bf
root
.
mu
.
Unlock
()
bf
dir
.
mu
.
Unlock
()
// mkdir takes filesystem treeLock - do it outside bfroot.mu
// mkfile takes filesystem treeLock - do it outside bfdir.mu
mkdir
(
bfroot
,
name
,
bfdir
)
mkfile
(
bfdir
,
name
,
f
)
mkdir
(
bfdir
,
"head"
,
bfhead
)
mkfile
(
bfhead
,
"data"
,
bfdata
)
mkfile
(
bfhead
,
"at"
,
NewSmallFile
(
bf
.
readAt
))
// TODO mtime(at) = tidtime(at)
// XXX mkfile(bh, "invalidations", bh.inv)
return
bfdir
.
Inode
(),
nil
// XXX fill out
return
f
.
Inode
(),
nil
}
}
// XXX do we need to support
rmdir
? (probably no)
// XXX do we need to support
unlink
? (probably no)
// /
bigfile/<bigfileX> -> Mkdir receives client request to create @<tid
>/.
// /
-> Mkdir receives client request to create @<rev
>/.
func
(
bfdir
*
BigFileDir
)
Mkdir
(
name
string
,
mode
uint32
,
fctx
*
fuse
.
Context
)
(
*
nodefs
.
Inode
,
fuse
.
Status
)
{
func
(
root
*
Root
)
Mkdir
(
name
string
,
mode
uint32
,
fctx
*
fuse
.
Context
)
(
*
nodefs
.
Inode
,
fuse
.
Status
)
{
inode
,
err
:=
bfdir
.
mkdir
(
name
,
fctx
)
// XXX ok to ignore mode?
inode
,
err
:=
root
.
mkdir
(
name
,
fctx
)
// XXX ok to ignore mode?
return
inode
,
err2LogStatus
(
err
)
return
inode
,
err2LogStatus
(
err
)
}
}
func
(
bfdir
*
BigFileDir
)
mkdir
(
name
string
,
fctx
*
fuse
.
Context
)
(
_
*
nodefs
.
Inode
,
err
error
)
{
func
(
root
*
Root
)
mkdir
(
name
string
,
fctx
*
fuse
.
Context
)
(
_
*
nodefs
.
Inode
,
err
error
)
{
defer
xerr
.
Contextf
(
&
err
,
"/
bigfile/%s: mkdir %q"
,
bfdir
.
oid
,
name
)
defer
xerr
.
Contextf
(
&
err
,
"/
: mkdir %q"
,
name
)
var
tid
zodb
.
Tid
var
rev
zodb
.
Tid
ok
:=
false
ok
:=
false
if
strings
.
HasPrefix
(
name
,
"@"
)
{
if
strings
.
HasPrefix
(
name
,
"@"
)
{
tid
,
err
=
zodb
.
ParseTid
(
name
[
1
:
])
rev
,
err
=
zodb
.
ParseTid
(
name
[
1
:
])
ok
=
(
err
==
nil
)
ok
=
(
err
==
nil
)
}
}
if
!
ok
{
if
!
ok
{
return
nil
,
eINVALf
(
"not @
tid
"
)
return
nil
,
eINVALf
(
"not @
rev
"
)
}
}
// check to see if dir(
tid
) is already there
// check to see if dir(
rev
) is already there
bfdir
.
m
u
.
Lock
()
root
.
zrevM
u
.
Lock
()
_
,
already
:=
bfdir
.
revTab
[
tid
]
_
,
already
:=
root
.
zrevTab
[
rev
]
bfdir
.
m
u
.
Unlock
()
root
.
zrevM
u
.
Unlock
()
if
already
{
if
already
{
return
nil
,
syscall
.
EEXIST
return
nil
,
syscall
.
EEXIST
}
}
// not there - without
bfdir lock proceed to open BigFile @tid
view of ZODB
// not there - without
zrevMu lock proceed to open @rev
view of ZODB
ctx
:=
asctx
(
fctx
)
ctx
:=
asctx
(
fctx
)
zconnRev
,
err
:=
groot
.
zopenAt
(
ctx
,
tid
)
zconnRev
,
err
:=
groot
.
zopenAt
(
ctx
,
rev
)
if
err
!=
nil
{
if
err
!=
nil
{
return
nil
,
err
return
nil
,
err
}
}
defer
zconnRev
.
Release
()
defer
zconnRev
.
Release
()
// XXX ok?
bf
,
err
:=
bigopen
(
ctx
,
zconnRev
,
bfdir
.
oid
)
// relock root and either mkdir or EEXIST if the directory was maybe
if
err
!=
nil
{
// simultanously created while we were not holding zrevMu.
return
nil
,
err
root
.
zrevMu
.
Lock
()
}
_
,
already
=
root
.
zrevTab
[
rev
]
defer
func
()
{
if
err
!=
nil
{
bf
.
Close
()
}
}()
// relock bfdir and either mkdir or EEXIST if the directory was maybe
// simultanously created while we were not holding bfroot.mu
bfdir
.
mu
.
Lock
()
_
,
already
=
bfdir
.
revTab
[
tid
]
if
already
{
if
already
{
bfdir
.
m
u
.
Unlock
()
root
.
zrevM
u
.
Unlock
()
return
nil
,
syscall
.
EEXIST
return
nil
,
syscall
.
EEXIST
}
}
bfrev
:=
&
BigFileRev
{
revDir
:=
&
Head
{
// XXX -> Rev ?
Node
:
nodefs
.
NewDefaultNode
(),
Node
:
nodefs
.
NewDefaultNode
(),
}
}
revdata
:=
&
BigFileData
{
root
.
zrevTab
[
rev
]
=
zconnRev
Node
:
nodefs
.
NewDefaultNode
(),
root
.
zrevMu
.
Unlock
()
bigfile
:
bf
,
loading
:
make
(
map
[
int64
]
*
blkLoadState
),
}
bfdir
.
revTab
[
tid
]
=
bfrev
// mkdir takes filesystem treeLock - do it outside zrevMu.
bfdir
.
mu
.
Unlock
()
mkdir
(
root
,
name
,
revDir
)
// mkdir takes filesystem treeLock - do it outside bfroot.mu
mkdir
(
bfdir
,
name
,
bfrev
)
mkfile
(
bfrev
,
"data"
,
revdata
)
return
bfrev
.
Inode
(),
nil
return
revDir
.
Inode
(),
nil
}
}
...
@@ -844,30 +799,28 @@ func bigopen(ctx context.Context, zconn *ZConn, oid zodb.Oid) (_ *BigFile, err e
...
@@ -844,30 +799,28 @@ func bigopen(ctx context.Context, zconn *ZConn, oid zodb.Oid) (_ *BigFile, err e
}
}
// Close release all resources of BigFile.
// Close release all resources of BigFile.
func
(
b
f
*
BigFile
)
Close
()
error
{
func
(
f
*
BigFile
)
Close
()
error
{
b
f
.
zbf
.
PDeactivate
()
f
.
zbf
.
PDeactivate
()
b
f
.
zbf
=
nil
f
.
zbf
=
nil
b
f
.
zconn
.
Release
()
f
.
zconn
.
Release
()
b
f
.
zconn
=
nil
f
.
zconn
=
nil
return
nil
return
nil
}
}
// /
bigfile/<bigfileX>/head/data
-> Getattr serves stat.
// /
(head|<rev>)/bigfile/<bigfileX>
-> Getattr serves stat.
func
(
bfdata
*
BigFileData
)
GetAttr
(
out
*
fuse
.
Attr
,
_
nodefs
.
File
,
fctx
*
fuse
.
Context
)
fuse
.
Status
{
func
(
f
*
BigFile
)
GetAttr
(
out
*
fuse
.
Attr
,
_
nodefs
.
File
,
fctx
*
fuse
.
Context
)
fuse
.
Status
{
// XXX locking
// XXX locking
bf
:=
bfdata
.
bigfile
out
.
Mode
=
fuse
.
S_IFREG
|
0444
out
.
Mode
=
fuse
.
S_IFREG
|
0444
out
.
Size
=
uint64
(
b
f
.
zbfSize
)
out
.
Size
=
uint64
(
f
.
zbfSize
)
// .Blocks
// .Blocks
// .Blksize
// .Blksize
// FIXME lastChange should cover all bigfile data, not only ZBigFile itself
// FIXME lastChange should cover all bigfile data, not only ZBigFile itself
//mtime := &
bfdata
.lastChange.Time().Time
//mtime := &
f
.lastChange.Time().Time
lastChange
:=
b
f
.
zbf
.
PSerial
()
lastChange
:=
f
.
zbf
.
PSerial
()
mtime
:=
lastChange
.
Time
()
.
Time
mtime
:=
lastChange
.
Time
()
.
Time
out
.
SetTimes
(
/*atime=*/
nil
,
/*mtime=*/
&
mtime
,
/*ctime=*/
&
mtime
)
out
.
SetTimes
(
/*atime=*/
nil
,
/*mtime=*/
&
mtime
,
/*ctime=*/
&
mtime
)
...
@@ -876,17 +829,16 @@ func (bfdata *BigFileData) GetAttr(out *fuse.Attr, _ nodefs.File, fctx *fuse.Con
...
@@ -876,17 +829,16 @@ func (bfdata *BigFileData) GetAttr(out *fuse.Attr, _ nodefs.File, fctx *fuse.Con
}
}
// /
bigfile/<bigfileX>/head/data
-> Read serves reading bigfile data.
// /
(head|<rev>)/bigfile/<bigfileX>
-> Read serves reading bigfile data.
func
(
bfdata
*
BigFileData
)
Read
(
_
nodefs
.
File
,
dest
[]
byte
,
off
int64
,
fctx
*
fuse
.
Context
)
(
fuse
.
ReadResult
,
fuse
.
Status
)
{
func
(
f
*
BigFile
)
Read
(
_
nodefs
.
File
,
dest
[]
byte
,
off
int64
,
fctx
*
fuse
.
Context
)
(
fuse
.
ReadResult
,
fuse
.
Status
)
{
// XXX locking
// XXX locking
bf
:=
bfdata
.
bigfile
zbf
:=
f
.
zbf
zbf
:=
bf
.
zbf
// cap read request to file size
// cap read request to file size
end
:=
off
+
int64
(
len
(
dest
))
// XXX overflow?
end
:=
off
+
int64
(
len
(
dest
))
// XXX overflow?
if
end
>
b
f
.
zbfSize
{
if
end
>
f
.
zbfSize
{
end
=
b
f
.
zbfSize
end
=
f
.
zbfSize
}
}
if
end
<=
off
{
if
end
<=
off
{
// XXX off >= size -> EINVAL? (but when size=0 kernel issues e.g. [0 +4K) read)
// XXX off >= size -> EINVAL? (but when size=0 kernel issues e.g. [0 +4K) read)
...
@@ -903,7 +855,7 @@ func (bfdata *BigFileData) Read(_ nodefs.File, dest []byte, off int64, fctx *fus
...
@@ -903,7 +855,7 @@ func (bfdata *BigFileData) Read(_ nodefs.File, dest []byte, off int64, fctx *fus
dest
=
make
([]
byte
,
aend
-
aoff
)
// ~> [aoff:aend) in file
dest
=
make
([]
byte
,
aend
-
aoff
)
// ~> [aoff:aend) in file
// XXX better ctx = transaction.PutIntoContext(ctx, txn)
// XXX better ctx = transaction.PutIntoContext(ctx, txn)
ctx
,
cancel
:=
xcontext
.
Merge
(
asctx
(
fctx
),
b
f
.
zconn
.
txnCtx
)
ctx
,
cancel
:=
xcontext
.
Merge
(
asctx
(
fctx
),
f
.
zconn
.
txnCtx
)
defer
cancel
()
defer
cancel
()
// read/load all block(s) in parallel
// read/load all block(s) in parallel
...
@@ -914,7 +866,7 @@ func (bfdata *BigFileData) Read(_ nodefs.File, dest []byte, off int64, fctx *fus
...
@@ -914,7 +866,7 @@ func (bfdata *BigFileData) Read(_ nodefs.File, dest []byte, off int64, fctx *fus
wg
.
Go
(
func
()
error
{
wg
.
Go
(
func
()
error
{
δ
:=
blkoff
-
aoff
// blk position in dest
δ
:=
blkoff
-
aoff
// blk position in dest
//log.Infof("readBlk #%d dest[%d:+%d]", blk, δ, zbf.blksize)
//log.Infof("readBlk #%d dest[%d:+%d]", blk, δ, zbf.blksize)
return
bfdata
.
readBlk
(
ctx
,
blk
,
dest
[
δ
:
δ
+
zbf
.
blksize
])
return
f
.
readBlk
(
ctx
,
blk
,
dest
[
δ
:
δ
+
zbf
.
blksize
])
})
})
}
}
...
@@ -929,23 +881,23 @@ func (bfdata *BigFileData) Read(_ nodefs.File, dest []byte, off int64, fctx *fus
...
@@ -929,23 +881,23 @@ func (bfdata *BigFileData) Read(_ nodefs.File, dest []byte, off int64, fctx *fus
// readBlk serves Read to read 1 ZBlk #blk into destination buffer.
// readBlk serves Read to read 1 ZBlk #blk into destination buffer.
//
//
// see "
6
) when we receive a FUSE read(#blk) request ..." in overview.
// see "
7
) when we receive a FUSE read(#blk) request ..." in overview.
//
//
// len(dest) == blksize.
// len(dest) == blksize.
func
(
bfdata
*
BigFileData
)
readBlk
(
ctx
context
.
Context
,
blk
int64
,
dest
[]
byte
)
error
{
func
(
f
*
BigFile
)
readBlk
(
ctx
context
.
Context
,
blk
int64
,
dest
[]
byte
)
error
{
// XXX errctx?
// XXX errctx?
// XXX locking
// XXX locking
// check if someone else is already loading this block
// check if someone else is already loading this block
bfdata
.
loadMu
.
Lock
()
f
.
loadMu
.
Lock
()
loading
,
already
:=
bfdata
.
loading
[
blk
]
loading
,
already
:=
f
.
loading
[
blk
]
if
!
already
{
if
!
already
{
loading
=
&
blkLoadState
{
loading
=
&
blkLoadState
{
ready
:
make
(
chan
struct
{}),
ready
:
make
(
chan
struct
{}),
}
}
bfdata
.
loading
[
blk
]
=
loading
f
.
loading
[
blk
]
=
loading
}
}
bfdata
.
loadMu
.
Unlock
()
f
.
loadMu
.
Unlock
()
// if it is already loading - just wait for it
// if it is already loading - just wait for it
if
already
{
if
already
{
...
@@ -963,14 +915,14 @@ func (bfdata *BigFileData) readBlk(ctx context.Context, blk int64, dest []byte)
...
@@ -963,14 +915,14 @@ func (bfdata *BigFileData) readBlk(ctx context.Context, blk int64, dest []byte)
// noone was loading - we became reponsible to load this block
// noone was loading - we became reponsible to load this block
zbf
:=
bfdata
.
bigfile
.
zbf
zbf
:=
f
.
zbf
blkdata
,
err
:=
zbf
.
LoadBlk
(
ctx
,
blk
)
// XXX -> +blkrevmax1
blkdata
,
err
:=
zbf
.
LoadBlk
(
ctx
,
blk
)
// XXX -> +blkrevmax1
loading
.
blkdata
=
blkdata
loading
.
blkdata
=
blkdata
loading
.
err
=
err
loading
.
err
=
err
close
(
loading
.
ready
)
close
(
loading
.
ready
)
// XXX before loading.ready?
// XXX before loading.ready?
blkrevmax2
,
_
:=
bfdata
.
bigfile
.
δFtail
.
LastRevOf
(
blk
,
zbf
.
PJar
()
.
At
())
blkrevmax2
,
_
:=
f
.
δFtail
.
LastRevOf
(
blk
,
zbf
.
PJar
()
.
At
())
//revmax := min(blkrevmax1, blkrevmax2)
//revmax := min(blkrevmax1, blkrevmax2)
revmax
:=
blkrevmax2
revmax
:=
blkrevmax2
_
=
revmax
_
=
revmax
...
@@ -979,7 +931,7 @@ func (bfdata *BigFileData) readBlk(ctx context.Context, blk int64, dest []byte)
...
@@ -979,7 +931,7 @@ func (bfdata *BigFileData) readBlk(ctx context.Context, blk int64, dest []byte)
// XXX remmapping
// XXX remmapping
// XXX -> own func?
// XXX -> own func?
// XXX locking
// XXX locking
for _, mapping := range
bfdata
.mappings {
for _, mapping := range
f
.mappings {
if revmax <= mapping.at || !mapping.blkrange.in(blk) {
if revmax <= mapping.at || !mapping.blkrange.in(blk) {
continue // do nothing
continue // do nothing
}
}
...
@@ -1001,9 +953,9 @@ func (bfdata *BigFileData) readBlk(ctx context.Context, blk int64, dest []byte)
...
@@ -1001,9 +953,9 @@ func (bfdata *BigFileData) readBlk(ctx context.Context, blk int64, dest []byte)
// data loaded with error - cleanup .loading
// data loaded with error - cleanup .loading
if
loading
.
err
!=
nil
{
if
loading
.
err
!=
nil
{
bfdata
.
loadMu
.
Lock
()
f
.
loadMu
.
Lock
()
delete
(
bfdata
.
loading
,
blk
)
delete
(
f
.
loading
,
blk
)
bfdata
.
loadMu
.
Unlock
()
f
.
loadMu
.
Unlock
()
return
err
return
err
}
}
...
@@ -1028,11 +980,11 @@ func (bfdata *BigFileData) readBlk(ctx context.Context, blk int64, dest []byte)
...
@@ -1028,11 +980,11 @@ func (bfdata *BigFileData) readBlk(ctx context.Context, blk int64, dest []byte)
// XXX locking - invalidation must make sure this workers are finished.
// XXX locking - invalidation must make sure this workers are finished.
// XXX if direct-io: don't touch pagecache
// XXX if direct-io: don't touch pagecache
st
:=
gfsconn
.
FileNotifyStoreCache
(
bfdata
.
Inode
(),
blk
*
zbf
.
blksize
,
blkdata
)
st
:=
gfsconn
.
FileNotifyStoreCache
(
f
.
Inode
(),
blk
*
zbf
.
blksize
,
blkdata
)
bfdata
.
loadMu
.
Lock
()
f
.
loadMu
.
Lock
()
delete
(
bfdata
.
loading
,
blk
)
delete
(
f
.
loading
,
blk
)
bfdata
.
loadMu
.
Unlock
()
f
.
loadMu
.
Unlock
()
if
st
==
fuse
.
OK
{
if
st
==
fuse
.
OK
{
return
return
...
@@ -1137,9 +1089,8 @@ func main() {
...
@@ -1137,9 +1089,8 @@ func main() {
// add entries to /
// add entries to /
mkfile
(
root
,
".wcfs"
,
NewStaticFile
([]
byte
(
zurl
)))
mkfile
(
root
,
".wcfs"
,
NewStaticFile
([]
byte
(
zurl
)))
mkdir
(
root
,
"
bigfile"
,
&
BigFileRoot
{
mkdir
(
root
,
"
head"
,
&
Head
{
Node
:
nodefs
.
NewDefaultNode
(),
Node
:
nodefs
.
NewDefaultNode
(),
tab
:
make
(
map
[
zodb
.
Oid
]
*
BigFileDir
),
})
})
// TODO handle autoexit
// TODO handle autoexit
...
...
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