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
748b40e8
Commit
748b40e8
authored
Feb 06, 2019
by
Kirill Smelkov
Browse files
Options
Browse Files
Download
Email Patches
Plain Diff
.
parent
ef12f1da
Changes
5
Hide whitespace changes
Inline
Side-by-side
Showing
5 changed files
with
186 additions
and
64 deletions
+186
-64
wcfs/internal/δbtree/zset_object.go
wcfs/internal/δbtree/zset_object.go
+54
-0
wcfs/internal/δbtree/δbtree.go
wcfs/internal/δbtree/δbtree.go
+30
-8
wcfs/misc.go
wcfs/misc.go
+18
-0
wcfs/wcfs.go
wcfs/wcfs.go
+67
-39
wcfs/zblk.go
wcfs/zblk.go
+17
-17
No files found.
wcfs/internal/δbtree/zset_object.go
0 → 100644
View file @
748b40e8
// Code generated by gen-set Object interface{}; DO NOT EDIT.
// Copyright (C) 2015-2019 Nexedi SA and Contributors.
// Kirill Smelkov <kirr@nexedi.com>
//
// This program is free software: you can Use, Study, Modify and Redistribute
// it under the terms of the GNU General Public License version 3, or (at your
// option) any later version, as published by the Free Software Foundation.
//
// You can also Link and Combine this program with other software covered by
// the terms of any of the Free Software licenses or any of the Open Source
// Initiative approved licenses and Convey the resulting work. Corresponding
// source of such a combination shall include the source code for all other
// software used.
//
// This program is distributed WITHOUT ANY WARRANTY; without even the implied
// warranty of MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE.
//
// See COPYING file for full licensing terms.
// See https://www.nexedi.com/licensing for rationale and options.
package
δbtree
// SetObject is a set of interface{}.
type
SetObject
map
[
interface
{}]
struct
{}
// Add adds v to the set.
func
(
s
SetObject
)
Add
(
v
interface
{})
{
s
[
v
]
=
struct
{}{}
}
// Has checks whether the set contains v.
func
(
s
SetObject
)
Has
(
v
interface
{})
bool
{
_
,
ok
:=
s
[
v
]
return
ok
}
// Update adds t values to s.
func
(
s
SetObject
)
Update
(
t
SetObject
)
{
for
v
:=
range
t
{
s
.
Add
(
v
)
}
}
// Elements returns all elements of set as slice.
func
(
s
SetObject
)
Elements
()
[]
interface
{}
{
ev
:=
make
([]
interface
{},
len
(
s
))
i
:=
0
for
e
:=
range
s
{
ev
[
i
]
=
e
i
++
}
return
ev
}
wcfs/internal/δbtree/δbtree.go
View file @
748b40e8
...
...
@@ -21,6 +21,7 @@
package
δbtree
//go:generate ../../gen-set δbtree Tree *Tree zset_tree.go
//go:generate ../../gen-set δbtree Object interface{} zset_object.go
import
(
"fmt"
...
...
@@ -39,17 +40,29 @@ type Bucket = btree.LOBucket
//
// PathSet is not safe for concurrent access.
type
PathSet
struct
{
// residency index
which maps
BTree|Bucket to top tree element.
// residency index
:
BTree|Bucket to top tree element.
residencyIdx
map
[
zodb
.
Oid
]
SetTree
// oid -> {} roots
// master index: tree root -> {} masters
masterIdx
map
[
*
Tree
]
SetObject
}
// NewPathSet creates new empty PathSet.
func
NewPathSet
()
*
PathSet
{
return
&
PathSet
{
residencyIdx
:
make
(
map
[
zodb
.
Oid
]
SetTree
),
masterIdx
:
make
(
map
[
*
Tree
]
SetObject
),
}
}
// Add adds path to collection.
// Add adds path to collection
and associates path root with master
.
//
// path[0] signifies a root.
// All path elemens must be Tree except last one which must be Bucket.
// A root can be associated with several masters (each provided on different Add call)
//
// XXX catch cycles on add?
func
(
m
*
PathSet
)
Add
(
path
[]
zodb
.
IPersistent
)
{
func
(
m
*
PathSet
)
Add
(
master
interface
{},
path
[]
zodb
.
IPersistent
)
{
l
:=
len
(
path
)
if
l
==
0
{
panic
(
"empty path"
)
...
...
@@ -81,17 +94,24 @@ func (m *PathSet) Add(path []zodb.IPersistent) {
}
nodeRoots
.
Add
(
root
)
}
masterSet
,
ok
:=
m
.
masterIdx
[
root
]
if
!
ok
{
masterSet
=
SetObject
{}
m
.
masterIdx
[
root
]
=
masterSet
}
masterSet
.
Add
(
master
)
}
// Invalidates returns which
tree
s are invalidated by changed objects.
// Invalidates returns which
master
s are invalidated by changed objects.
//
// returned are: roots of changed trees.
//
// XXX stub.
//
// TODO toposort changev wrt nodes ordering (defined by traversed paths) and do δbtree top-down.
func
(
m
*
PathSet
)
Invalidates
(
changev
[]
zodb
.
Oid
)
SetTree
{
toinvalidate
:=
make
(
SetTree
)
func
(
m
*
PathSet
)
Invalidates
(
changev
[]
zodb
.
Oid
)
(
masters
SetObject
)
{
masters
=
SetObject
{}
for
_
,
oid
:=
range
changev
{
roots
,
ok
:=
m
.
residencyIdx
[
oid
]
...
...
@@ -99,8 +119,10 @@ func (m *PathSet) Invalidates(changev []zodb.Oid) SetTree {
continue
// we don't know this oid
}
toinvalidate
.
Update
(
roots
)
for
root
:=
range
roots
{
masters
.
Update
(
m
.
masterIdx
[
root
])
}
}
return
toinvalidate
return
masters
}
wcfs/misc.go
View file @
748b40e8
...
...
@@ -511,3 +511,21 @@ func (u *zrevTabUnregister) AfterCompletion(txn transaction.Transaction) {
}
}
*/
// tidmax returns latest revision.
func
tidmax
(
a
,
b
zodb
.
Tid
)
zodb
.
Tid
{
if
a
>
b
{
return
a
}
else
{
return
b
}
}
// tidmin returns earliest revision.
func
tidmin
(
a
,
b
zodb
.
Tid
)
zodb
.
Tid
{
if
a
<
b
{
return
a
}
else
{
return
b
}
}
wcfs/wcfs.go
View file @
748b40e8
...
...
@@ -431,6 +431,7 @@ type Root struct {
// /(head|<rev>)/ - served by Head.
type
Head
struct
{
nodefs
.
Node
rev
zodb
.
Tid
// 0 for head/, !0 for @<rev>/
bfdir
*
BigFileDir
// bigfile/
// at - served by .readAt
...
...
@@ -457,11 +458,13 @@ type BigFileDir struct {
head
*
Head
// parent head/ or @<rev>/
// {} oid -> <bigfileX>
mu
sync
.
Mutex
fileMu
sync
.
Mutex
fileTab
map
[
zodb
.
Oid
]
*
BigFile
// visited BTree nodes -> which file + ordering for toposort on δbtree
blktabLoaded
*
δbtree
.
PathSet
// visited BTree nodes of all BigFiles
// -> which file + ordering for toposort on δbtree
indexMu
sync
.
Mutex
indexLooked
*
δbtree
.
PathSet
// XXX naming
}
// /(head|<rev>)/bigfile/<bigfileX> - served by BigFile.
...
...
@@ -599,7 +602,13 @@ func (root *Root) zδhandle1(zevent zodb.CommitEvent) {
zhead
:=
root
.
head
.
zconn
bfdir
:=
root
.
head
.
bfdir
toinvalidate
:=
map
[
*
BigFile
]
SetI64
{}
// {} file -> set(#blk)
// fileInvalidate describes invalidations for one file
type
fileInvalidate
struct
{
blkmap
SetI64
// changed blocks
size
bool
// whether to invalidate file sise
}
toinvalidate
:=
map
[
*
BigFile
]
*
fileInvalidate
{}
// {} file -> set(#blk), sizeChanged
btreeChangev
:=
[]
zodb
.
Oid
{}
// oids changing BTree|Bucket
fmt
.
Printf
(
"
\n\n\n
"
)
...
...
@@ -619,10 +628,10 @@ func (root *Root) zδhandle1(zevent zodb.CommitEvent) {
continue
// object not related to any bigfile
case
*
btree
.
LOBTree
:
// XXX -> δBTree
btreeChangev
=
append
(
btreeChangev
,
obj
.
POid
())
case
*
btree
.
LOBucket
:
// XXX -> δBTree
btreeChangev
=
append
(
btreeChangev
,
obj
.
POid
())
case
zBlk
:
// ZBlk*
// blkBoundTo locking: no other bindZFile are running,
...
...
@@ -640,12 +649,12 @@ func (root *Root) zδhandle1(zevent zodb.CommitEvent) {
continue
}
blkmap
,
ok
:=
toinvalidate
[
file
]
finv
,
ok
:=
toinvalidate
[
file
]
if
!
ok
{
blkmap
=
SetI64
{
}
toinvalidate
[
file
]
=
blkmap
finv
=
&
fileInvalidate
{
blkmap
:
SetI64
{}
}
toinvalidate
[
file
]
=
finv
}
blkmap
.
Update
(
objBlk
)
finv
.
blkmap
.
Update
(
objBlk
)
}
case
*
ZBigFile
:
...
...
@@ -659,15 +668,31 @@ func (root *Root) zδhandle1(zevent zodb.CommitEvent) {
runtime
.
KeepAlive
(
obj
)
}
// find out which files need to be invalidated due to index change
// XXX no indexMu lock needed because head is Locked
// XXX stub -> TODO full δbtree
fmt
.
Printf
(
"
\n
btreeChangev: %v
\n
"
,
btreeChangev
)
xfiles
:=
bfdir
.
indexLooked
.
Invalidates
(
btreeChangev
)
fmt
.
Printf
(
"xfiles: %v
\n
"
,
xfiles
)
for
xfile
:=
range
xfiles
{
file
:=
xfile
.
(
*
BigFile
)
finv
,
ok
:=
toinvalidate
[
file
]
if
!
ok
{
finv
=
&
fileInvalidate
{}
// XXX init blkmap?
toinvalidate
[
file
]
=
finv
}
finv
.
size
=
true
}
fmt
.
Printf
(
"
\n\n
zδhandle: toinvalidate (#%d):
\n
"
,
len
(
toinvalidate
))
for
file
:=
range
toinvalidate
{
fmt
.
Printf
(
"
\t
- %s
\n
"
,
file
.
zbf
.
POid
())
}
wg
,
ctx
:=
errgroup
.
WithContext
(
context
.
TODO
())
for
file
,
blkmap
:=
range
toinvalidate
{
for
file
,
finv
:=
range
toinvalidate
{
file
:=
file
for
blk
:=
range
blkmap
{
for
blk
:=
range
finv
.
blkmap
{
blk
:=
blk
wg
.
Go
(
func
()
error
{
return
file
.
invalidateBlk
(
ctx
,
blk
)
...
...
@@ -675,10 +700,12 @@ func (root *Root) zδhandle1(zevent zodb.CommitEvent) {
}
// invalidate kernel cache for attributes
// XXX we need to do it only if we see topoligy (i.e. btree) change
wg
.
Go
(
func
()
error
{
return
file
.
invalidateAttr
()
})
// we need to do it only if we see topoligy (i.e. btree) change
if
finv
.
size
{
wg
.
Go
(
func
()
error
{
return
file
.
invalidateAttr
()
})
}
}
err
:=
wg
.
Wait
()
if
err
!=
nil
{
...
...
@@ -688,12 +715,11 @@ func (root *Root) zδhandle1(zevent zodb.CommitEvent) {
// resync .zhead to zevent.tid
// XXX -> Head.Resync() ?
// 1. deactivate
all ZBigFile (we keep them
activated during whole txn)
// XXX dir.
m
u locking (not needed bcause zconnMu locked)
for
_
,
file
:=
range
bfdir
.
fileTab
{
// 1. deactivate
changed ZBigFile (we keep all ZBigFiles
activated during whole txn)
// XXX dir.
fileM
u locking (not needed bcause zconnMu locked)
for
file
:=
range
toinvalidate
{
file
.
zbf
.
PDeactivate
()
// XXX we need to reread size only for files in toinvalidate
file
.
zbfSize
=
-
1
// just in case
file
.
zbfSize
=
-
1
}
// 2. abort old and resync to new txn/at
...
...
@@ -702,10 +728,10 @@ func (root *Root) zδhandle1(zevent zodb.CommitEvent) {
zhead
.
Resync
(
txn
,
zevent
.
Tid
)
zhead
.
txnCtx
=
ctx
// 3. reactivate/restat
all
ZBigFile
// 3. reactivate/restat
invalidated
ZBigFile
// XXX -> parallel?
// XXX locking
for
_
,
file
:=
range
bfdir
.
fileTab
{
for
file
:=
range
toinvalidate
{
err
:=
file
.
zbf
.
PActivate
(
ctx
)
if
err
!=
nil
{
panic
(
err
)
// XXX
...
...
@@ -859,9 +885,9 @@ func (bfdir *BigFileDir) lookup(out *fuse.Attr, name string, fctx *fuse.Context)
}()
// check to see if dir(oid) is already there
bfdir
.
m
u
.
Lock
()
bfdir
.
fileM
u
.
Lock
()
f
,
already
:=
bfdir
.
fileTab
[
oid
]
bfdir
.
m
u
.
Unlock
()
bfdir
.
fileM
u
.
Unlock
()
if
already
{
return
f
,
nil
...
...
@@ -874,19 +900,19 @@ func (bfdir *BigFileDir) lookup(out *fuse.Attr, name string, fctx *fuse.Context)
}
// relock bfdir and either register f or, if the file was maybe
// simultanously created while we were not holding bfdir.
m
u, return that.
bfdir
.
m
u
.
Lock
()
// simultanously created while we were not holding bfdir.
fileM
u, return that.
bfdir
.
fileM
u
.
Lock
()
f2
,
already
:=
bfdir
.
fileTab
[
oid
]
if
already
{
bfdir
.
m
u
.
Unlock
()
bfdir
.
fileM
u
.
Unlock
()
f
.
Close
()
return
f2
,
nil
}
bfdir
.
fileTab
[
oid
]
=
f
bfdir
.
m
u
.
Unlock
()
bfdir
.
fileM
u
.
Unlock
()
// mkfile takes filesystem treeLock - do it outside bfdir.
m
u
// mkfile takes filesystem treeLock - do it outside bfdir.
fileM
u
mkfile
(
bfdir
,
name
,
f
)
return
f
,
nil
...
...
@@ -958,6 +984,7 @@ func (root *Root) mkdir(name string, fctx *fuse.Context) (_ *nodefs.Inode, err e
Node
:
newDefaultNode
(),
head
:
revDir
,
fileTab
:
make
(
map
[
zodb
.
Oid
]
*
BigFile
),
// indexLooked = nil for @revX/
}
revDir
.
bfdir
=
bfdir
...
...
@@ -1156,19 +1183,19 @@ func (f *BigFile) readBlk(ctx context.Context, blk int64, dest []byte) error {
// noone was loading - we became reponsible to load this block
zbf
:=
f
.
zbf
blkdata
,
treepath
,
blk
pathRevMax
,
err
:=
zbf
.
LoadBlk
(
ctx
,
blk
)
blkdata
,
treepath
,
pathRevMax
,
err
:=
zbf
.
LoadBlk
(
ctx
,
blk
)
loading
.
blkdata
=
blkdata
loading
.
err
=
err
close
(
loading
.
ready
)
// XXX locking
x
.
blktabVisited
.
Add
(
treepath
)
bfdir
:=
f
.
head
.
bfdir
bfdir
.
indexMu
.
Lock
()
// XXX locking correct?
bfdir
.
indexLooked
.
Add
(
f
,
treepath
)
// XXX needed only for head/
bfdir
.
indexMu
.
Unlock
()
// XXX before loading.ready?
blkrevmax
,
_
:=
f
.
δFtail
.
LastRevOf
(
blk
,
zbf
.
PJar
()
.
At
())
if
blkpathRevMax
<
blkrevmax
{
blkrevmax
=
blkpathRevMax
}
blkrevmax
=
tidmin
(
blkrevmax
,
pathRevMax
)
/*
// XXX remmapping - only if head.rev == 0
...
...
@@ -1343,9 +1370,10 @@ func main() {
zconn
:
zhead
,
}
bfdir
:=
&
BigFileDir
{
Node
:
newDefaultNode
(),
head
:
head
,
fileTab
:
make
(
map
[
zodb
.
Oid
]
*
BigFile
),
Node
:
newDefaultNode
(),
head
:
head
,
fileTab
:
make
(
map
[
zodb
.
Oid
]
*
BigFile
),
indexLooked
:
δbtree
.
NewPathSet
(),
}
head
.
bfdir
=
bfdir
...
...
wcfs/zblk.go
View file @
748b40e8
...
...
@@ -61,7 +61,9 @@ type zBlk interface {
//
// If returned data size is less than the block size of containing ZBigFile,
// the block trailing is assumed to be trailing \0.
loadBlkData
(
ctx
context
.
Context
)
([]
byte
,
error
)
//
// returns data and revision of ZBlk.
loadBlkData
(
ctx
context
.
Context
)
(
data
[]
byte
,
rev
zodb
.
Tid
,
_
error
)
// bindZFile associates ZBlk as being used by zfile to store block #blk.
//
...
...
@@ -155,16 +157,16 @@ func (zb *zBlk0State) PySetState(pystate interface{}) error {
return
nil
}
func
(
zb
*
ZBlk0
)
loadBlkData
(
ctx
context
.
Context
)
([]
byte
,
error
)
{
func
(
zb
*
ZBlk0
)
loadBlkData
(
ctx
context
.
Context
)
([]
byte
,
zodb
.
Tid
,
error
)
{
// XXX err ctx
err
:=
zb
.
PActivate
(
ctx
)
if
err
!=
nil
{
return
nil
,
err
return
nil
,
0
,
err
}
defer
zb
.
PDeactivate
()
return
mem
.
Bytes
(
zb
.
blkdata
),
nil
return
mem
.
Bytes
(
zb
.
blkdata
),
zb
.
PSerial
(),
nil
}
// ---- ZBlk1 ---
...
...
@@ -227,12 +229,12 @@ func (zb *zBlk1State) PySetState(pystate interface{}) error {
return
nil
}
func
(
zb
*
ZBlk1
)
loadBlkData
(
ctx
context
.
Context
)
([]
byte
,
error
)
{
func
(
zb
*
ZBlk1
)
loadBlkData
(
ctx
context
.
Context
)
([]
byte
,
zodb
.
Tid
,
error
)
{
// XXX errctx
err
:=
zb
.
PActivate
(
ctx
)
if
err
!=
nil
{
return
nil
,
err
return
nil
,
0
,
err
}
defer
zb
.
PDeactivate
()
...
...
@@ -337,12 +339,12 @@ func (zb *ZBlk1) loadBlkData(ctx context.Context) ([]byte, error) {
err
=
wg
.
Wait
()
if
err
!=
nil
{
return
nil
,
err
// XXX err ctx
return
nil
,
0
,
err
// XXX err ctx
}
// empty .chunktab -> ø
if
len
(
chunktab
)
==
0
{
return
nil
,
nil
return
nil
,
0
,
nil
}
// glue all chunks from chunktab
...
...
@@ -372,16 +374,16 @@ func (zb *ZBlk1) loadBlkData(ctx context.Context) ([]byte, error) {
for
_
,
start
:=
range
offv
[
:
len
(
offv
)
-
1
]
{
chunk
:=
chunktab
[
start
]
if
!
(
start
>=
stop
)
{
// verify chunks don't overlap
return
nil
,
fmt
.
Errorf
(
"!(start >= stop)"
)
// XXX
return
nil
,
0
,
fmt
.
Errorf
(
"!(start >= stop)"
)
// XXX
}
if
!
(
start
+
int32
(
len
(
chunk
.
data
))
<=
int32
(
len
(
blkdata
)))
{
// XXX overflow?
return
nil
,
fmt
.
Errorf
(
"blkdata overrun"
)
// XXX
return
nil
,
0
,
fmt
.
Errorf
(
"blkdata overrun"
)
// XXX
}
stop
=
start
+
int32
(
len
(
chunk
.
data
))
// XXX overflow?
copy
(
blkdata
[
start
:
],
chunk
.
data
)
}
return
blkdata
,
nil
return
blkdata
,
zb
.
PSerial
(),
nil
}
...
...
@@ -443,7 +445,7 @@ func (bf *zBigFileState) PySetState(pystate interface{}) (err error) {
// it also returns:
//
// - BTree path in .blktab for loaded block,
// - max
imum revision of nodes in the BTree path.
// - max
(_.serial for _ in ZBlk(#blk), all BTree/Bucket that lead to ZBlk)
//
// XXX better load into user-provided buf? mem.Buf?
func
(
bf
*
ZBigFile
)
LoadBlk
(
ctx
context
.
Context
,
blk
int64
)
(
_
[]
byte
,
treePath
[]
zodb
.
IPersistent
,
pathRevMax
zodb
.
Tid
,
err
error
)
{
...
...
@@ -458,10 +460,7 @@ func (bf *ZBigFile) LoadBlk(ctx context.Context, blk int64) (_ []byte, treePath
pathRevMax
=
0
xzblk
,
ok
,
err
:=
bf
.
blktab
.
GetTo
(
ctx
,
blk
,
func
(
node
zodb
.
IPersistent
)
{
treePath
=
append
(
treePath
,
node
)
rev
:=
node
.
PSerial
()
if
rev
>
pathRevMax
{
pathRevMax
=
rev
}
pathRevMax
=
tidmax
(
pathRevMax
,
node
.
PSerial
())
})
if
err
!=
nil
{
return
nil
,
nil
,
0
,
err
...
...
@@ -475,10 +474,11 @@ func (bf *ZBigFile) LoadBlk(ctx context.Context, blk int64) (_ []byte, treePath
return
nil
,
nil
,
0
,
fmt
.
Errorf
(
"expect ZBlk*; got %s"
,
typeOf
(
xzblk
))
}
blkdata
,
err
:=
zblk
.
loadBlkData
(
ctx
)
blkdata
,
blkrev
,
err
:=
zblk
.
loadBlkData
(
ctx
)
if
err
!=
nil
{
return
nil
,
nil
,
0
,
err
}
pathRevMax
=
tidmax
(
pathRevMax
,
blkrev
)
l
:=
int64
(
len
(
blkdata
))
if
l
>
bf
.
blksize
{
...
...
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