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
Issues
0
Issues
0
List
Boards
Labels
Milestones
Merge Requests
0
Merge Requests
0
Analytics
Analytics
Repository
Value Stream
Wiki
Wiki
Snippets
Snippets
Members
Members
Collapse sidebar
Close sidebar
Activity
Graph
Create a new issue
Commits
Issue Boards
Open sidebar
Joshua
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