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
11c95175
Commit
11c95175
authored
Jul 01, 2021
by
Kirill Smelkov
Browse files
Options
Browse Files
Download
Email Patches
Plain Diff
.
parent
042c5eeb
Changes
11
Hide whitespace changes
Inline
Side-by-side
Showing
11 changed files
with
340 additions
and
272 deletions
+340
-272
wcfs/internal/xbtree/blib/pptreesubset.go
wcfs/internal/xbtree/blib/pptreesubset.go
+3
-3
wcfs/internal/xbtree/treediff.go
wcfs/internal/xbtree/treediff.go
+34
-33
wcfs/internal/xbtree/xbtree.go
wcfs/internal/xbtree/xbtree.go
+0
-2
wcfs/internal/xbtree/xbtreetest/init/init.go
wcfs/internal/xbtree/xbtreetest/init/init.go
+105
-0
wcfs/internal/xbtree/xbtreetest/rtree.go
wcfs/internal/xbtree/xbtreetest/rtree.go
+16
-16
wcfs/internal/xbtree/xbtreetest/treeenv.go
wcfs/internal/xbtree/xbtreetest/treeenv.go
+40
-35
wcfs/internal/xbtree/xbtreetest/xbtreetest.go
wcfs/internal/xbtree/xbtreetest/xbtreetest.go
+12
-9
wcfs/internal/xbtree/xbtreetest/zdata.go
wcfs/internal/xbtree/xbtreetest/zdata.go
+68
-0
wcfs/internal/xbtree/δbtail.go
wcfs/internal/xbtree/δbtail.go
+17
-16
wcfs/internal/xbtree/δbtail_test.go
wcfs/internal/xbtree/δbtail_test.go
+44
-79
wcfs/internal/xbtree/δbtail_x_test.go
wcfs/internal/xbtree/δbtail_x_test.go
+1
-79
No files found.
wcfs/internal/xbtree/blib/pptreesubset.go
View file @
11c95175
...
...
@@ -102,7 +102,7 @@ func (S PPTreeSubSet) AddPath(path []zodb.Oid) {
// normalize path: remove embedded bucket and check whether it was an
// artificial empty tree.
path
=
n
ormPath
(
path
)
path
=
N
ormPath
(
path
)
// go through path and add nodes to the set
parent
:=
zodb
.
InvalidOid
...
...
@@ -132,11 +132,11 @@ func (S PPTreeSubSet) AddPath(path []zodb.Oid) {
}
}
//
n
ormPath normalizes path.
//
N
ormPath normalizes path.
//
// It removes embedded buckets and artificial empty trees.
// Returned slice is subslice of path and aliases its memory.
func
n
ormPath
(
path
[]
zodb
.
Oid
)
[]
zodb
.
Oid
{
func
N
ormPath
(
path
[]
zodb
.
Oid
)
[]
zodb
.
Oid
{
l
:=
len
(
path
)
// don't keep track of artificial empty tree
...
...
wcfs/internal/xbtree/treediff.go
View file @
11c95175
...
...
@@ -80,6 +80,7 @@ import (
"lab.nexedi.com/kirr/neo/go/zodb"
"lab.nexedi.com/nexedi/wendelin.core/wcfs/internal/xzodb"
"lab.nexedi.com/nexedi/wendelin.core/wcfs/internal/xbtree/blib"
)
const
traceDiff
=
false
...
...
@@ -113,7 +114,7 @@ func (δv ΔValue) String() string {
// for example for e.g. t₀->t₁->b₂ if δZ/T={t₀ b₂} -> δZ/TC=δZ/T+{t₁}
//
// δtopsByRoot = {} root -> {top changed nodes in that tree}
func
δZConnectTracked
(
δZv
[]
zodb
.
Oid
,
T
PPTreeSubSet
)
(
δZTC
setOid
,
δtopsByRoot
map
[
zodb
.
Oid
]
setOid
)
{
func
δZConnectTracked
(
δZv
[]
zodb
.
Oid
,
T
blib
.
PPTreeSubSet
)
(
δZTC
setOid
,
δtopsByRoot
map
[
zodb
.
Oid
]
setOid
)
{
δZ
:=
setOid
{};
for
_
,
δ
:=
range
δZv
{
δZ
.
Add
(
δ
)
}
δZTC
=
setOid
{}
δtopsByRoot
=
map
[
zodb
.
Oid
]
setOid
{}
...
...
@@ -338,18 +339,18 @@ func (rs rangeSplit) String() string {
// δtops is set of top nodes for changed subtrees.
// δZTC is connected(δZ/T) - connected closure for subset of δZ(old..new) that
// touches tracked nodes of T.
func
treediff
(
ctx
context
.
Context
,
root
zodb
.
Oid
,
δtops
setOid
,
δZTC
setOid
,
trackSet
PPTreeSubSet
,
zconnOld
,
zconnNew
*
zodb
.
Connection
)
(
δT
map
[
Key
]
ΔValue
,
δtrack
*
ΔPPTreeSubSet
,
δtkeycov
*
RangedKeySet
,
err
error
)
{
func
treediff
(
ctx
context
.
Context
,
root
zodb
.
Oid
,
δtops
setOid
,
δZTC
setOid
,
trackSet
blib
.
PPTreeSubSet
,
zconnOld
,
zconnNew
*
zodb
.
Connection
)
(
δT
map
[
Key
]
ΔValue
,
δtrack
*
blib
.
ΔPPTreeSubSet
,
δtkeycov
*
blib
.
RangedKeySet
,
err
error
)
{
defer
xerr
.
Contextf
(
&
err
,
"treediff %s..%s %s"
,
zconnOld
.
At
(),
zconnNew
.
At
(),
root
)
δT
=
map
[
Key
]
ΔValue
{}
δtrack
=
NewΔPPTreeSubSet
()
δtkeycov
=
&
RangedKeySet
{}
δtrack
=
blib
.
NewΔPPTreeSubSet
()
δtkeycov
=
&
blib
.
RangedKeySet
{}
tracefDiff
(
"
\n
treediff %s δtops: %v δZTC: %v
\n
"
,
root
,
δtops
,
δZTC
)
tracefDiff
(
" trackSet: %v
\n
"
,
trackSet
)
defer
tracefDiff
(
"
\n
-> δT: %v
\n
δtrack: %v
\n
δtkeycov: %v
\n
"
,
δT
,
δtrack
,
δtkeycov
)
δtrackv
:=
[]
*
ΔPPTreeSubSet
{}
δtrackv
:=
[]
*
blib
.
ΔPPTreeSubSet
{}
for
top
:=
range
δtops
{
// XXX -> sorted?
a
,
err1
:=
zgetNodeOrNil
(
ctx
,
zconnOld
,
top
)
...
...
@@ -401,7 +402,7 @@ func treediff(ctx context.Context, root zodb.Oid, δtops setOid, δZTC setOid, t
// consistent with b (= a + δ).
//
// δtkeycov represents how δtrack grows (always grows) tracking set key coverage.
func
diffX
(
ctx
context
.
Context
,
a
,
b
Node
,
δZTC
setOid
,
trackSet
PPTreeSubSet
)
(
δ
map
[
Key
]
ΔValue
,
δtrack
*
ΔPPTreeSubSet
,
δtkeycov
*
RangedKeySet
,
err
error
)
{
func
diffX
(
ctx
context
.
Context
,
a
,
b
Node
,
δZTC
setOid
,
trackSet
blib
.
PPTreeSubSet
)
(
δ
map
[
Key
]
ΔValue
,
δtrack
*
blib
.
ΔPPTreeSubSet
,
δtkeycov
*
blib
.
RangedKeySet
,
err
error
)
{
if
a
==
nil
&&
b
==
nil
{
panic
(
"BUG: both a & b == nil"
)
// XXX -> not a bug e.g. for `ø ø T` sequence?
}
...
...
@@ -438,11 +439,11 @@ func diffX(ctx context.Context, a, b Node, δZTC setOid, trackSet PPTreeSubSet)
if
isT
{
return
diffT
(
ctx
,
aT
,
bT
,
δZTC
,
trackSet
)
}
else
{
var
δtrack
*
ΔPPTreeSubSet
var
δtrack
*
blib
.
ΔPPTreeSubSet
δ
,
err
:=
diffB
(
ctx
,
aB
,
bB
)
if
δ
!=
nil
{
δtrack
=
NewΔPPTreeSubSet
()
δtkeycov
=
&
RangedKeySet
{}
δtrack
=
blib
.
NewΔPPTreeSubSet
()
δtkeycov
=
&
blib
.
RangedKeySet
{}
}
return
δ
,
δtrack
,
δtkeycov
,
err
}
...
...
@@ -452,13 +453,13 @@ func diffX(ctx context.Context, a, b Node, δZTC setOid, trackSet PPTreeSubSet)
//
// a, b point to top of subtrees @old and @new revisions.
// δZTC is connected set of objects covering δZT (objects changed in this tree in old..new).
func
diffT
(
ctx
context
.
Context
,
A
,
B
*
Tree
,
δZTC
setOid
,
trackSet
PPTreeSubSet
)
(
δ
map
[
Key
]
ΔValue
,
δtrack
*
ΔPPTreeSubSet
,
δtkeycov
*
RangedKeySet
,
err
error
)
{
func
diffT
(
ctx
context
.
Context
,
A
,
B
*
Tree
,
δZTC
setOid
,
trackSet
blib
.
PPTreeSubSet
)
(
δ
map
[
Key
]
ΔValue
,
δtrack
*
blib
.
ΔPPTreeSubSet
,
δtkeycov
*
blib
.
RangedKeySet
,
err
error
)
{
tracefDiff
(
" diffT %s %s
\n
"
,
xidOf
(
A
),
xidOf
(
B
))
defer
xerr
.
Contextf
(
&
err
,
"diffT %s %s"
,
xidOf
(
A
),
xidOf
(
B
))
δ
=
map
[
Key
]
ΔValue
{}
δtrack
=
NewΔPPTreeSubSet
()
δtkeycov
=
&
RangedKeySet
{}
δtrack
=
blib
.
NewΔPPTreeSubSet
()
δtkeycov
=
&
blib
.
RangedKeySet
{}
defer
func
()
{
tracefDiff
(
" -> δ: %v
\n
"
,
δ
)
tracefDiff
(
" -> δtrack: %v
\n
"
,
δtrack
)
...
...
@@ -564,22 +565,22 @@ ABcov:
Bv
:=
rangeSplit
{
btop
}
// nodes expanded from B
// for phase 2:
Akqueue
:=
&
RangedKeySet
{}
// queue for keys in A to be processed for δ-
Bkqueue
:=
&
RangedKeySet
{}
// ----//---- in B for δ+
Akdone
:=
&
RangedKeySet
{}
// already processed keys in A
Bkdone
:=
&
RangedKeySet
{}
// ----//---- in B
Aktodo
:=
func
(
r
KeyRange
)
{
Akqueue
:=
&
blib
.
RangedKeySet
{}
// queue for keys in A to be processed for δ-
Bkqueue
:=
&
blib
.
RangedKeySet
{}
// ----//---- in B for δ+
Akdone
:=
&
blib
.
RangedKeySet
{}
// already processed keys in A
Bkdone
:=
&
blib
.
RangedKeySet
{}
// ----//---- in B
Aktodo
:=
func
(
r
blib
.
KeyRange
)
{
if
!
Akdone
.
HasRange
(
r
)
{
δtodo
:=
&
RangedKeySet
{}
δtodo
:=
&
blib
.
RangedKeySet
{}
δtodo
.
AddRange
(
r
)
δtodo
.
DifferenceInplace
(
Akdone
)
debugfDiff
(
" Akq <- %s
\n
"
,
δtodo
)
Akqueue
.
UnionInplace
(
δtodo
)
}
}
Bktodo
:=
func
(
r
KeyRange
)
{
Bktodo
:=
func
(
r
blib
.
KeyRange
)
{
if
!
Bkdone
.
HasRange
(
r
)
{
δtodo
:=
&
RangedKeySet
{}
δtodo
:=
&
blib
.
RangedKeySet
{}
δtodo
.
AddRange
(
r
)
δtodo
.
DifferenceInplace
(
Bkdone
)
debugfDiff
(
" Bkq <- %s
\n
"
,
δtodo
)
...
...
@@ -595,8 +596,8 @@ ABcov:
}
// δtkeycov will be = BAdd \ ADel
δtkeycovADel
:=
&
RangedKeySet
{}
δtkeycovBAdd
:=
&
RangedKeySet
{}
δtkeycovADel
:=
&
blib
.
RangedKeySet
{}
δtkeycovBAdd
:=
&
blib
.
RangedKeySet
{}
// phase 1: expand A top->down driven by δZTC.
// by default a node contributes to δ-
...
...
@@ -620,7 +621,7 @@ ABcov:
// a is bucket -> δ-
δA
,
err
:=
diffB
(
ctx
,
a
,
nil
);
/*X*/
if
err
!=
nil
{
return
nil
,
nil
,
nil
,
err
}
err
=
δMerge
(
δ
,
δA
);
/*X*/
if
err
!=
nil
{
return
nil
,
nil
,
nil
,
err
}
ar
:=
KeyRange
{
ra
.
lo
,
ra
.
hi_
}
ar
:=
blib
.
KeyRange
{
ra
.
lo
,
ra
.
hi_
}
δtrack
.
Del
.
AddPath
(
ra
.
Path
())
δtkeycovADel
.
AddRange
(
ar
)
debugfDiff
(
" δtrack - %s %v
\n
"
,
ar
,
ra
.
Path
())
...
...
@@ -632,7 +633,7 @@ ABcov:
case
*
Tree
:
// empty tree - queue holes covered by it
if
len
(
a
.
Entryv
())
==
0
{
ar
:=
KeyRange
{
ra
.
lo
,
ra
.
hi_
}
ar
:=
blib
.
KeyRange
{
ra
.
lo
,
ra
.
hi_
}
δtrack
.
Del
.
AddPath
(
ra
.
Path
())
δtkeycovADel
.
AddRange
(
ar
)
debugfDiff
(
" δtrack - %s %v
\n
"
,
ar
,
ra
.
Path
())
...
...
@@ -691,8 +692,8 @@ ABcov:
}
if
found
{
// ac can be skipped if key coverage stays the same
ar
:=
KeyRange
{
ac
.
lo
,
ac
.
hi_
}
br
:=
KeyRange
{
bc
.
lo
,
bc
.
hi_
}
ar
:=
blib
.
KeyRange
{
ac
.
lo
,
ac
.
hi_
}
br
:=
blib
.
KeyRange
{
bc
.
lo
,
bc
.
hi_
}
if
ar
==
br
{
// adjust trackSet since path to the node could have changed
apath
:=
ac
.
Path
()
...
...
@@ -744,7 +745,7 @@ ABcov:
}
for
_
,
r
:=
range
Bkqueue
.
AllRanges
()
{
lo
:=
r
.
l
o
lo
:=
r
.
L
o
for
{
b
,
err
:=
Bv
.
GetToLeaf
(
ctx
,
lo
);
/*X*/
if
err
!=
nil
{
return
nil
,
nil
,
nil
,
err
}
debugfDiff
(
" B k%d -> %s
\n
"
,
lo
,
b
)
...
...
@@ -758,7 +759,7 @@ ABcov:
// δ <- δB
err
=
δMerge
(
δ
,
δB
);
/*X*/
if
err
!=
nil
{
return
nil
,
nil
,
nil
,
err
}
br
:=
KeyRange
{
b
.
lo
,
b
.
hi_
}
br
:=
blib
.
KeyRange
{
b
.
lo
,
b
.
hi_
}
δtrack
.
Add
.
AddPath
(
b
.
Path
())
δtkeycovBAdd
.
AddRange
(
br
)
debugfDiff
(
" δtrack + %s %v
\n
"
,
br
,
b
.
Path
())
...
...
@@ -771,7 +772,7 @@ ABcov:
}
// continue with next right bucket until r coverage is complete
if
r
.
h
i_
<=
b
.
hi_
{
if
r
.
H
i_
<=
b
.
hi_
{
break
}
lo
=
b
.
hi_
+
1
...
...
@@ -782,7 +783,7 @@ ABcov:
debugfDiff
(
"
\n
"
)
debugfDiff
(
" Akq: %s
\n
"
,
Akqueue
)
for
_
,
r
:=
range
Akqueue
.
AllRanges
()
{
lo
:=
r
.
l
o
lo
:=
r
.
L
o
for
{
a
,
err
:=
Av
.
GetToLeaf
(
ctx
,
lo
);
/*X*/
if
err
!=
nil
{
return
nil
,
nil
,
nil
,
err
}
debugfDiff
(
" A k%d -> %s
\n
"
,
lo
,
a
)
...
...
@@ -798,7 +799,7 @@ ABcov:
err
=
δMerge
(
δ
,
δA
);
/*X*/
if
err
!=
nil
{
return
nil
,
nil
,
nil
,
err
}
δtrack
.
Del
.
AddPath
(
a
.
Path
())
// NOTE adjust δtkeycovADel only if a was originally tracked
ar
:=
KeyRange
{
a
.
lo
,
a
.
hi_
}
ar
:=
blib
.
KeyRange
{
a
.
lo
,
a
.
hi_
}
_
,
tracked
:=
trackSet
[
a
.
node
.
POid
()]
if
tracked
{
δtkeycovADel
.
AddRange
(
ar
)
...
...
@@ -815,7 +816,7 @@ ABcov:
}
// continue with next right bucket until r coverage is complete
if
r
.
h
i_
<=
a
.
hi_
{
if
r
.
H
i_
<=
a
.
hi_
{
break
}
lo
=
a
.
hi_
+
1
...
...
@@ -1009,7 +1010,7 @@ func xidOf(obj zodb.IPersistent) string {
func
(
rn
*
nodeInRange
)
String
()
string
{
done
:=
" "
;
if
rn
.
done
{
done
=
"*"
}
return
fmt
.
Sprintf
(
"%s%s%s"
,
done
,
KeyRange
{
rn
.
lo
,
rn
.
hi_
},
vnode
(
rn
.
node
))
return
fmt
.
Sprintf
(
"%s%s%s"
,
done
,
blib
.
KeyRange
{
rn
.
lo
,
rn
.
hi_
},
vnode
(
rn
.
node
))
}
// push pushes element to node stack.
...
...
wcfs/internal/xbtree/xbtree.go
View file @
11c95175
...
...
@@ -5,10 +5,8 @@ package xbtree
import
(
"fmt"
"math"
"lab.nexedi.com/kirr/neo/go/zodb"
"lab.nexedi.com/kirr/neo/go/zodb/btree"
"lab.nexedi.com/nexedi/wendelin.core/wcfs/internal/set"
"lab.nexedi.com/nexedi/wendelin.core/wcfs/internal/xbtree/blib"
...
...
wcfs/internal/xbtree/xbtreetest/init/init.go
0 → 100644
View file @
11c95175
// Copyright (C) 2020-2021 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 xbtreetest/init (ex imported from package A) should be imported in
// addition to xbtreetest (from package A_test) to initialize xbtreetest at runtime.
package
init
// ZBlk-related part of δbtail_test
import
(
"context"
"fmt"
"lab.nexedi.com/kirr/go123/xerr"
"lab.nexedi.com/kirr/neo/go/zodb"
"lab.nexedi.com/nexedi/wendelin.core/wcfs/internal/xbtree"
"lab.nexedi.com/nexedi/wendelin.core/wcfs/internal/xzodb"
"lab.nexedi.com/nexedi/wendelin.core/wcfs/internal/zdata"
)
type
Tree
=
xbtree
.
Tree
type
Node
=
xbtree
.
Node
type
Key
=
xbtree
.
Key
type
ZBlk
=
zdata
.
ZBlk
// ztreeGetBlk returns ztree[k] and tree path that lead to this block.
// XXX +return blkRevMax and use it ?
func
ztreeGetBlk
(
ctx
context
.
Context
,
ztree
*
Tree
,
k
Key
)
(
zblk
ZBlk
,
ok
bool
,
path
[]
Node
,
err
error
)
{
path
=
[]
Node
{}
xzblk
,
ok
,
err
:=
ztree
.
VGet
(
ctx
,
k
,
func
(
node
Node
)
{
path
=
append
(
path
,
node
)
})
if
err
!=
nil
{
return
nil
,
false
,
nil
,
err
}
if
ok
{
zblk
,
ok
=
xzblk
.
(
ZBlk
)
if
!
ok
{
return
nil
,
false
,
nil
,
fmt
.
Errorf
(
"expect ZBlk*; got %s"
,
xzodb
.
TypeOf
(
xzblk
))
// XXX errctx
}
}
return
zblk
,
ok
,
path
,
nil
}
func
init
()
{
xbtree
.
ZTreeGetBlkData
=
ZTreeGetBlkData
xbtree
.
ZGetBlkData
=
ZGetBlkData
}
// ZTreeGetBlkData returns block data from block pointed to by ztree[k].
func
ZTreeGetBlkData
(
ctx
context
.
Context
,
ztree
*
Tree
,
k
Key
)
(
data
string
,
ok
bool
,
path
[]
Node
,
err
error
)
{
defer
xerr
.
Contextf
(
&
err
,
"@%s: tree<%s>: get blkdata from [%d]"
,
ztree
.
PJar
()
.
At
(),
ztree
.
POid
(),
k
)
zblk
,
ok
,
path
,
err
:=
ztreeGetBlk
(
ctx
,
ztree
,
k
)
if
err
!=
nil
||
!
ok
{
return
""
,
ok
,
path
,
err
}
bdata
,
_
,
err
:=
zblk
.
LoadBlkData
(
ctx
)
if
err
!=
nil
{
return
""
,
false
,
nil
,
err
}
return
string
(
bdata
),
true
,
path
,
nil
}
// ZGetBlkData loads block data from ZBlk object specified by its oid.
func
ZGetBlkData
(
ctx
context
.
Context
,
zconn
*
zodb
.
Connection
,
zblkOid
zodb
.
Oid
)
(
data
string
,
err
error
)
{
defer
xerr
.
Contextf
(
&
err
,
"@%s: get blkdata from obj %s"
,
zconn
.
At
(),
zblkOid
)
xblk
,
err
:=
zconn
.
Get
(
ctx
,
zblkOid
)
if
err
!=
nil
{
return
""
,
err
}
zblk
,
ok
:=
xblk
.
(
ZBlk
)
if
!
ok
{
return
""
,
fmt
.
Errorf
(
"expect ZBlk*; got %s"
,
xzodb
.
TypeOf
(
xblk
))
}
bdata
,
_
,
err
:=
zblk
.
LoadBlkData
(
ctx
)
if
err
!=
nil
{
return
""
,
err
}
return
string
(
bdata
),
nil
}
wcfs/internal/xbtree/xbtreetest/rtree.go
View file @
11c95175
...
...
@@ -31,27 +31,27 @@ import (
// RTree represents Tree node covering [lo, hi_] key range in its parent tree.
// XXX actually no coverage here -> kill? -> change to just `path []zodb.Oid` in RBucket?
type
RTree
struct
{
o
id
zodb
.
Oid
p
arent
*
RTree
O
id
zodb
.
Oid
P
arent
*
RTree
// XXX +children?
}
// RBucket represents Bucket node covering [lo, hi_] key range in its Tree.
// NOTE it is not [lo,hi) but [lo,hi_] instead to avoid overflow at KeyMax.
type
RBucket
struct
{
o
id
zodb
.
Oid
p
arent
*
RTree
lo
,
hi_
Key
// XXX -> KeyRange ?
kv
map
[
Key
]
string
// bucket's k->v; values were ZBlk objects whose data is loaded instead.
O
id
zodb
.
Oid
P
arent
*
RTree
Keycov
blib
.
KeyRange
KV
map
[
Key
]
string
// bucket's k->v; values were ZBlk objects whose data is loaded instead.
}
// Path returns path to this bucket from tree root.
func
(
rb
*
RBucket
)
Path
()
[]
zodb
.
Oid
{
path
:=
[]
zodb
.
Oid
{
rb
.
o
id
}
p
:=
rb
.
p
arent
path
:=
[]
zodb
.
Oid
{
rb
.
O
id
}
p
:=
rb
.
P
arent
for
p
!=
nil
{
path
=
append
([]
zodb
.
Oid
{
p
.
o
id
},
path
...
)
p
=
p
.
p
arent
path
=
append
([]
zodb
.
Oid
{
p
.
O
id
},
path
...
)
p
=
p
.
P
arent
}
return
path
}
...
...
@@ -63,15 +63,15 @@ type RBucketSet []*RBucket // k↑
// Get returns RBucket which covers key k.
func
(
rbs
RBucketSet
)
Get
(
k
Key
)
*
RBucket
{
i
:=
sort
.
Search
(
len
(
rbs
),
func
(
i
int
)
bool
{
return
k
<=
rbs
[
i
]
.
h
i_
return
k
<=
rbs
[
i
]
.
Keycov
.
H
i_
})
if
i
==
len
(
rbs
)
{
panicf
(
"BUG: key %v not covered; coverage: %s"
,
k
,
rbs
.
coverage
())
}
rb
:=
rbs
[
i
]
if
!
(
rb
.
lo
<=
k
&&
k
<=
rb
.
h
i_
)
{
panicf
(
"BUG: get(%v) ->
[%v, %v]; coverage: %s"
,
k
,
rb
.
lo
,
rb
.
hi_
,
rbs
.
coverage
())
if
!
(
rb
.
Keycov
.
Lo
<=
k
&&
k
<=
rb
.
Keycov
.
H
i_
)
{
panicf
(
"BUG: get(%v) ->
%s; coverage: %s"
,
k
,
rb
.
Keycov
,
rbs
.
coverage
())
}
return
rb
...
...
@@ -87,7 +87,7 @@ func (rbs RBucketSet) coverage() string {
if
s
!=
""
{
s
+=
" "
}
s
+=
fmt
.
Sprintf
(
"
[%v, %v]"
,
rb
.
lo
,
rb
.
hi_
)
s
+=
fmt
.
Sprintf
(
"
%s"
,
rb
.
Keycov
)
}
return
s
}
...
...
@@ -96,7 +96,7 @@ func (rbs RBucketSet) coverage() string {
func
(
xkv
RBucketSet
)
Flatten
()
map
[
Key
]
string
{
kv
:=
make
(
map
[
Key
]
string
)
for
_
,
b
:=
range
xkv
{
for
k
,
v
:=
range
b
.
kv
{
for
k
,
v
:=
range
b
.
KV
{
kv
[
k
]
=
v
}
}
...
...
@@ -104,5 +104,5 @@ func (xkv RBucketSet) Flatten() map[Key]string {
}
func
(
b
*
RBucket
)
String
()
string
{
return
fmt
.
Sprintf
(
"%sB%s{%s}"
,
b
lib
.
KeyRange
{
b
.
lo
,
b
.
hi_
},
b
.
oid
,
kvtxt
(
b
.
kv
))
return
fmt
.
Sprintf
(
"%sB%s{%s}"
,
b
.
Keycov
,
b
.
Oid
,
kvtxt
(
b
.
KV
))
}
wcfs/internal/xbtree/xbtreetest/treeenv.go
View file @
11c95175
...
...
@@ -18,7 +18,7 @@
// See https://www.nexedi.com/licensing for rationale and options.
package
xbtreetest
// T
reeEnv
+ friends
// T + friends
import
(
"context"
...
...
@@ -28,14 +28,15 @@ import (
"lab.nexedi.com/kirr/neo/go/transaction"
"lab.nexedi.com/kirr/neo/go/zodb"
"lab.nexedi.com/nexedi/wendelin.core/wcfs/internal/xbtree/blib"
"lab.nexedi.com/nexedi/wendelin.core/wcfs/internal/xzodb"
)
//
tTreeEnv
is tree-based testing environment.
//
T
is tree-based testing environment.
//
// It combines TreeSrv and client side access to ZODB with committed trees.
// It should be created it via
tNewTreeEnv
().
type
tTreeEnv
struct
{
// It should be created it via
NewT
().
type
T
struct
{
*
testing
.
T
work
string
// working directory
...
...
@@ -44,13 +45,13 @@ type tTreeEnv struct {
db
*
zodb
.
DB
// all committed trees
commitv
[]
*
tTree
Commit
commitv
[]
*
Commit
}
//
tTree
Commit represent test commit changing a tree.
type
tTree
Commit
struct
{
// Commit represent test commit changing a tree.
type
Commit
struct
{
tree
string
// the tree in topology-encoding
prev
*
tTreeCommit
// previous commit
prev
*
Commit
// previous commit
at
zodb
.
Tid
// commit revision
δZ
*
zodb
.
EventCommit
// raw ZODB changes; δZ.tid == at
xkv
RBucketSet
// full tree state as of @at
...
...
@@ -59,12 +60,12 @@ type tTreeCommit struct {
// δzblkData map[zodb.Oid]Δstring // full diff for zblkData against parent XXX ?
}
//
tNewTreeEnv creates new tTreeEnv
.
func
tNewTreeEnv
(
t
*
testing
.
T
)
*
tTreeEnv
{
//
NewT creates new T
.
func
NewT
(
t
*
testing
.
T
)
*
T
{
X
:=
exc
.
Raiseif
t
.
Helper
()
tt
:=
&
tTreeEnv
{
T
:
t
}
tt
:=
&
T
{
T
:
t
}
var
err
error
work
:=
t
.
TempDir
()
...
...
@@ -91,7 +92,7 @@ func tNewTreeEnv(t *testing.T) *tTreeEnv {
})
head
:=
tt
.
treeSrv
.
head
t1
:=
&
tTree
Commit
{
t1
:=
&
Commit
{
tree
:
"T/B:"
,
// treegen.py creates the tree as initially empty
prev
:
nil
,
at
:
head
,
...
...
@@ -100,7 +101,7 @@ func tNewTreeEnv(t *testing.T) *tTreeEnv {
δZ
:
nil
,
δxkv
:
nil
,
}
tt
.
commitv
=
[]
*
tTree
Commit
{
t1
}
tt
.
commitv
=
[]
*
Commit
{
t1
}
return
tt
}
...
...
@@ -115,17 +116,18 @@ func (_ *tZODBCacheEverything) PCacheClassify(_ zodb.IPersistent) zodb.PCachePol
}
// Root returns OID of root tree node.
func
(
t
*
tTreeEnv
)
Root
()
zodb
.
Oid
{
func
(
t
*
T
)
Root
()
zodb
.
Oid
{
return
t
.
treeSrv
.
treeRoot
}
// Head returns most-recently committed tree.
func
(
t
*
tTreeEnv
)
Head
()
*
tTree
Commit
{
func
(
t
*
T
)
Head
()
*
Commit
{
return
t
.
commitv
[
len
(
t
.
commitv
)
-
1
]
}
// CommitTree calls t.treeSrv.Commit and returns tTreeCommit corresponding to committed transaction.
func
(
t
*
tTreeEnv
)
CommitTree
(
tree
string
)
*
tTreeCommit
{
// CommitTree calls t.treeSrv.Commit and returns Commit corresponding to committed transaction.
// XXX naming -> Commit ?
func
(
t
*
T
)
CommitTree
(
tree
string
)
*
Commit
{
// TODO X = FatalIf
X
:=
exc
.
Raiseif
defer
exc
.
Contextf
(
"commit %s"
,
tree
)
...
...
@@ -164,19 +166,18 @@ func (t *tTreeEnv) CommitTree(tree string) *tTreeCommit {
// it comes to ->T2.
xkv
=
RBucketSet
{
&
RBucket
{
o
id
:
zodb
.
InvalidOid
,
p
arent
:
&
RTree
{
o
id
:
t
.
Root
(),
// NOTE oid is not InvalidOid
p
arent
:
nil
,
O
id
:
zodb
.
InvalidOid
,
P
arent
:
&
RTree
{
O
id
:
t
.
Root
(),
// NOTE oid is not InvalidOid
P
arent
:
nil
,
},
lo
:
KeyMin
,
hi_
:
KeyMax
,
kv
:
map
[
Key
]
string
{},
Keycov
:
blib
.
KeyRange
{
KeyMin
,
KeyMax
},
KV
:
map
[
Key
]
string
{},
},
}
}
ttree
:=
&
tTree
Commit
{
ttree
:=
&
Commit
{
tree
:
tree
,
at
:
δZ
.
Tid
,
δZ
:
δZ
,
...
...
@@ -244,7 +245,7 @@ func xGetBlkDataTab(db *zodb.DB, at zodb.Tid) map[zodb.Oid]string {
// xgetBlkData loads blk data for ZBlk<oid> @t.at
//
// For speed the load is done via preloaded t.blkDataTab instead of access to the DB.
func
(
t
*
tTree
Commit
)
xgetBlkData
(
oid
zodb
.
Oid
)
string
{
func
(
t
*
Commit
)
xgetBlkData
(
oid
zodb
.
Oid
)
string
{
if
oid
==
VDEL
{
return
DEL
}
...
...
@@ -282,15 +283,14 @@ func xGetTree(db *zodb.DB, at zodb.Tid, root zodb.Oid) RBucketSet {
})
if
len
(
rbucketv
)
==
0
{
// empty tree -> [-∞,∞){}
etree
:=
&
RTree
{
o
id
:
root
,
p
arent
:
nil
,
O
id
:
root
,
P
arent
:
nil
,
}
ebucket
:=
&
RBucket
{
oid
:
zodb
.
InvalidOid
,
parent
:
etree
,
lo
:
KeyMin
,
hi_
:
KeyMax
,
kv
:
map
[
Key
]
string
{},
Oid
:
zodb
.
InvalidOid
,
Parent
:
etree
,
Keycov
:
blib
.
KeyRange
{
KeyMin
,
KeyMax
},
KV
:
map
[
Key
]
string
{},
}
rbucketv
=
RBucketSet
{
ebucket
}
}
...
...
@@ -307,7 +307,7 @@ func _xwalkDFS(ctx context.Context, lo, hi_ Key, ztree *Tree, rparent *RTree, bv
err
:=
ztree
.
PActivate
(
ctx
);
X
(
err
)
defer
ztree
.
PDeactivate
()
rtree
:=
&
RTree
{
oid
:
ztree
.
POid
(),
p
arent
:
rparent
}
rtree
:=
&
RTree
{
Oid
:
ztree
.
POid
(),
P
arent
:
rparent
}
// [i].Key ≤ [i].Child.*.Key < [i+1].Key i ∈ [0, len([]))
//
...
...
@@ -346,7 +346,12 @@ func _xwalkDFS(ctx context.Context, lo, hi_ Key, ztree *Tree, rparent *RTree, bv
}
b
:=
&
RBucket
{
oid
:
zbucket
.
POid
(),
parent
:
rtree
,
lo
:
xlo
,
hi_
:
xhi_
,
kv
:
bkv
}
b
:=
&
RBucket
{
Oid
:
zbucket
.
POid
(),
Parent
:
rtree
,
Keycov
:
blib
.
KeyRange
{
xlo
,
xhi_
},
KV
:
bkv
,
}
bvisit
(
b
)
}
}
...
...
wcfs/internal/xbtree/xbtreetest/xbtreetest.go
View file @
11c95175
...
...
@@ -23,24 +23,27 @@ package xbtreetest
import
(
"fmt"
"math"
"lab.nexedi.com/kirr/neo/go/zodb"
"lab.nexedi.com/kirr/neo/go/zodb/btree"
"lab.nexedi.com/nexedi/wendelin.core/wcfs/internal/set"
// "lab.nexedi.com/nexedi/wendelin.core/wcfs/internal/xbtree
"
"lab.nexedi.com/nexedi/wendelin.core/wcfs/internal/xbtree/blib
"
)
// XXX dup from xbtree (to avoid import cycle)
type
Tree
=
btree
.
LOBTree
type
Bucket
=
btree
.
LOBucket
// XXX instead of generics
type
Tree
=
blib
.
Tree
type
Bucket
=
blib
.
Bucket
type
Node
=
blib
.
Node
type
TreeEntry
=
blib
.
TreeEntry
type
BucketEntry
=
blib
.
BucketEntry
type
Key
=
blib
.
Key
const
KeyMax
=
blib
.
KeyMax
const
KeyMin
=
blib
.
KeyMin
type
Key
=
int64
const
KeyMax
Key
=
math
.
MaxInt64
const
KeyMin
Key
=
math
.
MinInt64
type
setKey
=
set
.
I64
// XXX dup from xbtree (to avoid import cycle)
const
VDEL
=
zodb
.
InvalidOid
...
...
wcfs/internal/xbtree/xbtreetest/zdata.go
0 → 100644
View file @
11c95175
// Copyright (C) 2020-2021 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
xbtreetest
// access to ZBlk data
import
(
"context"
"lab.nexedi.com/kirr/go123/exc"
"lab.nexedi.com/kirr/neo/go/transaction"
"lab.nexedi.com/kirr/neo/go/zodb"
_
"lab.nexedi.com/kirr/neo/go/zodb/wks"
)
// ZBlk-related functions are imported at runtime by package xbtreetest/init
var
(
ZTreeGetBlkData
func
(
context
.
Context
,
*
Tree
,
Key
)
(
string
,
bool
,
[]
Node
,
error
)
ZGetBlkData
func
(
context
.
Context
,
*
zodb
.
Connection
,
zodb
.
Oid
)
(
string
,
error
)
)
func
zassertInitDone
()
{
if
ZTreeGetBlkData
==
nil
{
panic
(
"xbtreetest/zdata not initialized -> import xbtreetest/init to fix"
)
}
}
// xzgetBlkData loads block data from ZBlk object specified by its oid.
func
xzgetBlkData
(
ctx
context
.
Context
,
zconn
*
zodb
.
Connection
,
zblkOid
zodb
.
Oid
)
string
{
zassertInitDone
()
X
:=
exc
.
Raiseif
if
zblkOid
==
VDEL
{
return
DEL
}
data
,
err
:=
ZGetBlkData
(
ctx
,
zconn
,
zblkOid
);
X
(
err
)
return
string
(
data
)
}
// xzgetBlkDataAt loads block data from ZBlk object specified by oid@at.
func
xzgetBlkDataAt
(
db
*
zodb
.
DB
,
zblkOid
zodb
.
Oid
,
at
zodb
.
Tid
)
string
{
zassertInitDone
()
X
:=
exc
.
Raiseif
txn
,
ctx
:=
transaction
.
New
(
context
.
Background
())
defer
txn
.
Abort
()
zconn
,
err
:=
db
.
Open
(
ctx
,
&
zodb
.
ConnOptions
{
At
:
at
});
X
(
err
)
return
xzgetBlkData
(
ctx
,
zconn
,
zblkOid
)
}
wcfs/internal/xbtree/δbtail.go
View file @
11c95175
...
...
@@ -30,6 +30,7 @@ import (
"lab.nexedi.com/kirr/neo/go/transaction"
"lab.nexedi.com/kirr/neo/go/zodb"
"lab.nexedi.com/nexedi/wendelin.core/wcfs/internal/xbtree/blib"
"lab.nexedi.com/nexedi/wendelin.core/wcfs/internal/xtail"
)
...
...
@@ -96,7 +97,7 @@ type ΔBtail struct {
// For this set all vδT are fully computed.
// The set of nodes that were requested to be tracked, but were not yet
// taken into account, is kept in ΔTtail.trackNew & co.
trackSet
PPTreeSubSet
trackSet
blib
.
PPTreeSubSet
// set of trees for which .trackNew is non-empty
trackNewRoots
setOid
...
...
@@ -114,7 +115,7 @@ type ΔTtail struct {
// set of nodes that were requested to be tracked in this tree, but for
// which vδT was not yet rebuilt
trackNew
PPTreeSubSet
trackNew
blib
.
PPTreeSubSet
// XXX + trackNewKeys RangedKeySet
// {}k/v @tail for keys that are changed in (tail, head].
...
...
@@ -158,7 +159,7 @@ func NewΔBtail(at0 zodb.Tid, db *zodb.DB) *ΔBtail {
δZtail
:
zodb
.
NewΔTail
(
at0
),
vδBroots
:
nil
,
vδTbyRoot
:
map
[
zodb
.
Oid
]
*
ΔTtail
{},
trackSet
:
PPTreeSubSet
{},
trackSet
:
blib
.
PPTreeSubSet
{},
trackNewRoots
:
setOid
{},
db
:
db
,
}
...
...
@@ -167,7 +168,7 @@ func NewΔBtail(at0 zodb.Tid, db *zodb.DB) *ΔBtail {
// newΔTtail creates new empty ΔTtail object.
func
newΔTtail
()
*
ΔTtail
{
return
&
ΔTtail
{
trackNew
:
PPTreeSubSet
{},
trackNew
:
blib
.
PPTreeSubSet
{},
KVAtTail
:
make
(
map
[
Key
]
Value
),
lastRevOf
:
make
(
map
[
Key
]
zodb
.
Tid
),
}
...
...
@@ -271,7 +272,7 @@ func (δBtail *ΔBtail) track(key Key, path []zodb.Oid) error {
// empty artificial tree. We need to do the normalization because we
// later check whether leaf path[-1] ∈ trackSet and without
// normalization path[-1] can be InvalidOid.
path
=
n
ormPath
(
path
)
path
=
blib
.
N
ormPath
(
path
)
if
len
(
path
)
==
0
{
return
nil
// empty tree
}
...
...
@@ -334,7 +335,7 @@ func (δBtail *ΔBtail) rebuildAll() (err error) {
// - set of revisions for which new entries in .vδT have been created.
//
// XXX place
func
(
δTtail
*
ΔTtail
)
rebuild
(
root
zodb
.
Oid
,
δZtail
*
zodb
.
ΔTail
,
db
*
zodb
.
DB
)
(
δtrackSet
PPTreeSubSet
,
δrevSet
setTid
,
err
error
)
{
func
(
δTtail
*
ΔTtail
)
rebuild
(
root
zodb
.
Oid
,
δZtail
*
zodb
.
ΔTail
,
db
*
zodb
.
DB
)
(
δtrackSet
blib
.
PPTreeSubSet
,
δrevSet
setTid
,
err
error
)
{
defer
xerr
.
Context
(
&
err
,
"ΔTtail rebuild"
)
// XXX locking
...
...
@@ -342,7 +343,7 @@ func (δTtail *ΔTtail) rebuild(root zodb.Oid, δZtail *zodb.ΔTail, db *zodb.DB
tracefΔBtail
(
"trackNew: %v
\n
"
,
δTtail
.
trackNew
)
trackNew
:=
δTtail
.
trackNew
δTtail
.
trackNew
=
PPTreeSubSet
{}
δTtail
.
trackNew
=
blib
.
PPTreeSubSet
{}
if
len
(
trackNew
)
==
0
{
return
nil
,
nil
,
nil
...
...
@@ -353,7 +354,7 @@ func (δTtail *ΔTtail) rebuild(root zodb.Oid, δZtail *zodb.ΔTail, db *zodb.DB
// go backwards and merge vδT <- treediff(lo..hi/trackNew)
vδZ
:=
δZtail
.
Data
()
for
{
δtkeycov
:=
&
RangedKeySet
{}
// all keys coming into tracking set during this lo<-hi scan
δtkeycov
:=
&
blib
.
RangedKeySet
{}
// all keys coming into tracking set during this lo<-hi scan
trackNewCur
:=
trackNew
.
Clone
()
// trackNew adjusted as of when going to i<- entry
for
i
:=
len
(
vδZ
)
-
1
;
i
>=
0
;
i
--
{
δZ
:=
vδZ
[
i
]
...
...
@@ -411,7 +412,7 @@ func (δTtail *ΔTtail) rebuild(root zodb.Oid, δZtail *zodb.ΔTail, db *zodb.DB
// widenTrackNew widens trackNew to cover δtkeycov.
// XXX -> widenTrackSet?
func
widenTrackNew
(
trackNew
PPTreeSubSet
,
δtkeycov
*
RangedKeySet
,
root
zodb
.
Oid
,
at
zodb
.
Tid
,
db
*
zodb
.
DB
)
(
err
error
)
{
func
widenTrackNew
(
trackNew
blib
.
PPTreeSubSet
,
δtkeycov
*
blib
.
RangedKeySet
,
root
zodb
.
Oid
,
at
zodb
.
Tid
,
db
*
zodb
.
DB
)
(
err
error
)
{
// XXX errctx, debug
defer
xerr
.
Contextf
(
&
err
,
"widenTrackNew tree<%s> @%s +%s"
,
root
,
at
,
δtkeycov
)
...
...
@@ -430,13 +431,13 @@ func widenTrackNew(trackNew PPTreeSubSet, δtkeycov *RangedKeySet, root zodb.Oid
top
:=
&
nodeInRange
{
prefix
:
nil
,
lo
:
KeyMin
,
hi_
:
KeyMax
,
node
:
tree
}
V
:=
rangeSplit
{
top
}
for
_
,
r
:=
range
δtkeycov
.
AllRanges
()
{
lo
:=
r
.
l
o
lo
:=
r
.
L
o
for
{
b
,
err
:=
V
.
GetToLeaf
(
ctx
,
lo
);
/*X*/
if
err
!=
nil
{
return
err
}
trackNew
.
AddPath
(
b
.
Path
())
// continue with next right bucket until r coverage is complete
if
r
.
h
i_
<=
b
.
hi_
{
if
r
.
H
i_
<=
b
.
hi_
{
break
}
lo
=
b
.
hi_
+
1
...
...
@@ -450,7 +451,7 @@ func widenTrackNew(trackNew PPTreeSubSet, δtkeycov *RangedKeySet, root zodb.Oid
//
// δtrackNew/δtkeycov represents how trackNew changes when going through `atPrev <- δZ.Rev` .
// newRevEntry indicates whether δZ.Rev was not there before in .vδT and new corresponding δT entry was created.
func
(
δTtail
*
ΔTtail
)
rebuild1
(
atPrev
zodb
.
Tid
,
δZ
zodb
.
ΔRevEntry
,
trackNew
PPTreeSubSet
,
db
*
zodb
.
DB
)
(
δtrackNew
*
ΔPPTreeSubSet
,
δtkeycov
*
RangedKeySet
,
newRevEntry
bool
,
err
error
)
{
func
(
δTtail
*
ΔTtail
)
rebuild1
(
atPrev
zodb
.
Tid
,
δZ
zodb
.
ΔRevEntry
,
trackNew
blib
.
PPTreeSubSet
,
db
*
zodb
.
DB
)
(
δtrackNew
*
blib
.
ΔPPTreeSubSet
,
δtkeycov
*
blib
.
RangedKeySet
,
newRevEntry
bool
,
err
error
)
{
defer
xerr
.
Contextf
(
&
err
,
"rebuild1 %s<-%s"
,
atPrev
,
δZ
.
Rev
)
debugfΔBtail
(
"
\n
rebuild1 @%s <- @%s
\n
"
,
atPrev
,
δZ
.
Rev
)
...
...
@@ -467,7 +468,7 @@ func (δTtail *ΔTtail) rebuild1(atPrev zodb.Tid, δZ zodb.ΔRevEntry, trackNew
// skip opening DB connections if there is no change to this tree
if
len
(
δtopsByRoot
)
==
0
{
return
NewΔPPTreeSubSet
(),
&
RangedKeySet
{},
false
,
nil
return
blib
.
NewΔPPTreeSubSet
(),
&
blib
.
RangedKeySet
{},
false
,
nil
}
if
len
(
δtopsByRoot
)
!=
1
{
...
...
@@ -560,7 +561,7 @@ func (δBtail *ΔBtail) Update(δZ *zodb.EventCommit) (_ ΔB, err error) {
// δtkeycov1 != ø -> rebuild δTtail with trackNew ~= δtkeycov1
if
!
δT1
.
δtkeycov1
.
Empty
()
&&
δBtail
.
δZtail
.
Len
()
>
1
{
trackNew
:=
PPTreeSubSet
{}
trackNew
:=
blib
.
PPTreeSubSet
{}
err
:=
widenTrackNew
(
trackNew
,
δT1
.
δtkeycov1
,
root
,
δBtail
.
Head
(),
δBtail
.
db
)
if
err
!=
nil
{
return
ΔB
{},
err
...
...
@@ -611,8 +612,8 @@ type _ΔBUpdate1 struct {
ByRoot
map
[
zodb
.
Oid
]
*
_ΔTUpdate1
}
type
_ΔTUpdate1
struct
{
δtkeycov1
*
RangedKeySet
// {} root -> δtrackedKeys after first treediff (always grow)
δtrack
*
ΔPPTreeSubSet
// XXX kill (not used)
δtkeycov1
*
blib
.
RangedKeySet
// {} root -> δtrackedKeys after first treediff (always grow)
δtrack
*
blib
.
ΔPPTreeSubSet
// XXX kill (not used)
}
func
(
δBtail
*
ΔBtail
)
_Update1
(
δZ
*
zodb
.
EventCommit
)
(
δB1
_ΔBUpdate1
,
err
error
)
{
headOld
:=
δBtail
.
Head
()
...
...
wcfs/internal/xbtree/δbtail_test.go
View file @
11c95175
...
...
@@ -44,17 +44,11 @@ package xbtree
// - to generate set of random tree topologies that all correspond to particular {k->v} dict.
import
(
"bufio"
"context"
"flag"
"fmt"
"io"
"math"
"math/rand"
"os"
"os/exec"
"reflect"
"regexp"
"sort"
"strings"
"testing"
...
...
@@ -62,16 +56,18 @@ import (
"lab.nexedi.com/kirr/go123/exc"
"lab.nexedi.com/kirr/go123/xerr"
"lab.nexedi.com/kirr/neo/go/transaction"
"lab.nexedi.com/kirr/neo/go/zodb"
_
"lab.nexedi.com/kirr/neo/go/zodb/wks"
"lab.nexedi.com/nexedi/wendelin.core/wcfs/internal/xbtree/blib"
"lab.nexedi.com/nexedi/wendelin.core/wcfs/internal/xbtree/xbtreetest"
// "lab.nexedi.com/nexedi/wendelin.core/wcfs/internal/xzodb"
)
type
Δstring
=
xbtreetest
.
Δstring
// trackSet returns what should be ΔBtail.trackSet coverage for specified tracked key set.
func
(
rbs
RBucketSet
)
trackSet
(
tracked
setKey
)
PPTreeSubSet
{
func
(
rbs
xbtreetest
.
RBucketSet
)
trackSet
(
tracked
setKey
)
blib
.
PPTreeSubSet
{
// nil = don't compute keyCover
// (trackSet is called from inside hot inner loop of rebuild test)
trackSet
:=
rbs
.
_trackSetWithCov
(
tracked
,
nil
)
...
...
@@ -79,23 +75,23 @@ func (rbs RBucketSet) trackSet(tracked setKey) PPTreeSubSet {
}
// trackSetWithCov returns what should be ΔBtail.trackSet and its key coverage for specified tracked key set.
func
(
rbs
RBucketSet
)
trackSetWithCov
(
tracked
setKey
)
(
trackSet
PPTreeSubSet
,
keyCover
*
RangedKeySet
)
{
keyCover
=
&
RangedKeySet
{}
func
(
rbs
xbtreetest
.
RBucketSet
)
trackSetWithCov
(
tracked
setKey
)
(
trackSet
blib
.
PPTreeSubSet
,
keyCover
*
blib
.
RangedKeySet
)
{
keyCover
=
&
blib
.
RangedKeySet
{}
trackSet
=
rbs
.
_trackSetWithCov
(
tracked
,
keyCover
)
return
trackSet
,
keyCover
}
func
(
rbs
RBucketSet
)
_trackSetWithCov
(
tracked
setKey
,
outKeyCover
*
RangedKeySet
)
(
trackSet
PPTreeSubSet
)
{
trackSet
=
PPTreeSubSet
{}
func
(
rbs
xbtreetest
.
RBucketSet
)
_trackSetWithCov
(
tracked
setKey
,
outKeyCover
*
blib
.
RangedKeySet
)
(
trackSet
blib
.
PPTreeSubSet
)
{
trackSet
=
blib
.
PPTreeSubSet
{}
for
k
:=
range
tracked
{
kb
:=
rbs
.
Get
(
k
)
if
outKeyCover
!=
nil
{
outKeyCover
.
AddRange
(
KeyRange
{
kb
.
lo
,
kb
.
hi_
}
)
outKeyCover
.
AddRange
(
kb
.
Keycov
)
}
// trackSet explicitly records only regular buckets.
// embedded buckets all have oid=zodb.InvalidOid and would lead to z
newNode
:=
false
if
kb
.
o
id
!=
zodb
.
InvalidOid
{
if
kb
.
O
id
!=
zodb
.
InvalidOid
{
track
,
already
:=
trackSet
[
kb
.
oid
]
if
!
already
{
track
=
&
nodeInTree
{
parent
:
kb
.
parent
.
oid
,
nchild
:
0
}
...
...
@@ -138,7 +134,7 @@ func (rbs RBucketSet) _trackSetWithCov(tracked setKey, outKeyCover *RangedKeySet
// XGetδKV translates {k -> δ<oid>} to {k -> δ(ZBlk(oid).data)} according to t1..t2 db snapshots.
func
XGetδKV
(
t1
,
t2
*
tTree
Commit
,
δkvOid
map
[
Key
]
ΔValue
)
map
[
Key
]
Δstring
{
func
XGetδKV
(
t1
,
t2
*
xbtreetest
.
Commit
,
δkvOid
map
[
Key
]
ΔValue
)
map
[
Key
]
Δstring
{
δkv
:=
make
(
map
[
Key
]
Δstring
,
len
(
δkvOid
))
for
k
,
δvOid
:=
range
δkvOid
{
δkv
[
k
]
=
Δstring
{
...
...
@@ -217,7 +213,7 @@ func (kadjA KAdjMatrix) Mul(kadjB KAdjMatrix) KAdjMatrix {
// This set of keys defaults to allTestKeys(t1,t2).
//
// KAdj itself is verified by testΔBTail on entries with .kadjOK set.
func
KAdj
(
t1
,
t2
*
tTree
Commit
,
keysv
...
setKey
)
(
kadj
KAdjMatrix
)
{
func
KAdj
(
t1
,
t2
*
xbtreetest
.
Commit
,
keysv
...
setKey
)
(
kadj
KAdjMatrix
)
{
// assert KAdj(A,B) == KAdj(B,A)
kadj12
:=
_KAdj
(
t1
,
t2
,
keysv
...
)
kadj21
:=
_KAdj
(
t2
,
t1
,
keysv
...
)
...
...
@@ -235,7 +231,7 @@ func debugfKAdj(format string, argv ...interface{}) {
}
}
func
_KAdj
(
t1
,
t2
*
tTree
Commit
,
keysv
...
setKey
)
(
kadj
KAdjMatrix
)
{
func
_KAdj
(
t1
,
t2
*
xbtreetest
.
Commit
,
keysv
...
setKey
)
(
kadj
KAdjMatrix
)
{
var
keys
setKey
switch
len
(
keysv
)
{
case
0
:
...
...
@@ -261,10 +257,10 @@ func _KAdj(t1, t2 *tTreeCommit, keysv ...setKey) (kadj KAdjMatrix) {
adj1
:=
setKey
{}
adj2
:=
setKey
{}
q1
:=
&
RangedKeySet
{};
q1
.
Add
(
k
)
q2
:=
&
RangedKeySet
{};
q2
.
Add
(
k
)
done1
:=
&
RangedKeySet
{}
done2
:=
&
RangedKeySet
{}
q1
:=
&
blib
.
RangedKeySet
{};
q1
.
Add
(
k
)
q2
:=
&
blib
.
RangedKeySet
{};
q2
.
Add
(
k
)
done1
:=
&
blib
.
RangedKeySet
{}
done2
:=
&
blib
.
RangedKeySet
{}
debugfKAdj
(
"
\n
k%s
\n
"
,
kstr
(
k
))
for
!
q1
.
Empty
()
||
!
q2
.
Empty
()
{
...
...
@@ -281,10 +277,10 @@ func _KAdj(t1, t2 *tTreeCommit, keysv ...setKey) (kadj KAdjMatrix) {
debugfKAdj
(
" adj1 += %s
\t
-> %s
\n
"
,
kstr
(
k_
),
adj1
)
}
}
b1r
:=
KeyRange
{
b1
.
lo
,
b1
.
hi_
}
b1r
:=
blib
.
KeyRange
{
b1
.
lo
,
b1
.
hi_
}
done1
.
AddRange
(
b1r
)
// q2 |= (b1.keyrange \ done2)
δq2
:=
&
RangedKeySet
{}
δq2
:=
&
blib
.
RangedKeySet
{}
δq2
.
AddRange
(
b1r
)
δq2
.
DifferenceInplace
(
done2
)
q2
.
UnionInplace
(
δq2
)
...
...
@@ -310,10 +306,10 @@ func _KAdj(t1, t2 *tTreeCommit, keysv ...setKey) (kadj KAdjMatrix) {
debugfKAdj
(
" adj2 += %s
\t
-> %s
\n
"
,
kstr
(
k_
),
adj2
)
}
}
b2r
:=
KeyRange
{
b2
.
lo
,
b2
.
hi_
}
b2r
:=
blib
.
KeyRange
{
b2
.
lo
,
b2
.
hi_
}
done2
.
AddRange
(
b2r
)
// q1 |= (b2.keyrange \ done1)
δq1
:=
&
RangedKeySet
{}
δq1
:=
&
blib
.
RangedKeySet
{}
δq1
.
AddRange
(
b2r
)
δq1
.
DifferenceInplace
(
done1
)
q1
.
UnionInplace
(
δq1
)
...
...
@@ -343,7 +339,7 @@ func _KAdj(t1, t2 *tTreeCommit, keysv ...setKey) (kadj KAdjMatrix) {
// the cycling phase of update, that is responsible to recompute older
// entries when key coverage grows, is exercised by
// xverifyΔBTail_rebuild.
func
xverifyΔBTail_Update
(
t
*
testing
.
T
,
subj
string
,
db
*
zodb
.
DB
,
treeRoot
zodb
.
Oid
,
t1
,
t2
*
tTree
Commit
)
{
func
xverifyΔBTail_Update
(
t
*
testing
.
T
,
subj
string
,
db
*
zodb
.
DB
,
treeRoot
zodb
.
Oid
,
t1
,
t2
*
xbtreetest
.
Commit
)
{
// verify transition at1->at2 for all initial states of tracked {keys} from kv1 + kv2 + ∞
t
.
Run
(
fmt
.
Sprintf
(
"Update/%s→%s"
,
t1
.
tree
,
t2
.
tree
),
func
(
t
*
testing
.
T
)
{
...
...
@@ -370,7 +366,7 @@ func xverifyΔBTail_Update(t *testing.T, subj string, db *zodb.DB, treeRoot zodb
// xverifyΔBTail_Update1 verifies how ΔBTail handles ZODB update at1->at2 from initial
// tracked state defined by initialTrackedKeys.
func
xverifyΔBTail_Update1
(
t
*
testing
.
T
,
subj
string
,
db
*
zodb
.
DB
,
treeRoot
zodb
.
Oid
,
t1
,
t2
*
tTree
Commit
,
initialTrackedKeys
setKey
,
kadj
KAdjMatrix
)
{
func
xverifyΔBTail_Update1
(
t
*
testing
.
T
,
subj
string
,
db
*
zodb
.
DB
,
treeRoot
zodb
.
Oid
,
t1
,
t2
*
xbtreetest
.
Commit
,
initialTrackedKeys
setKey
,
kadj
KAdjMatrix
)
{
X
:=
exc
.
Raiseif
//t.Logf("\n>>> Track=%s\n", initialTrackedKeys)
...
...
@@ -423,7 +419,7 @@ func xverifyΔBTail_Update1(t *testing.T, subj string, db *zodb.DB, treeRoot zod
if
oid2
==
zodb
.
InvalidOid
{
// embedded bucket
oid2
=
leaf2
.
parent
.
oid
}
if
δZset
.
Has
(
oid1
)
||
δZset
.
Has
(
oid2
)
||
(
KeyRange
{
leaf1
.
lo
,
leaf1
.
hi_
}
!=
KeyRange
{
leaf2
.
lo
,
leaf2
.
hi_
})
{
if
δZset
.
Has
(
oid1
)
||
δZset
.
Has
(
oid2
)
||
(
blib
.
KeyRange
{
leaf1
.
lo
,
leaf1
.
hi_
}
!=
blib
.
KeyRange
{
leaf2
.
lo
,
leaf2
.
hi_
})
{
TrackedδZ
.
Add
(
k
)
}
}
...
...
@@ -452,7 +448,7 @@ func xverifyΔBTail_Update1(t *testing.T, subj string, db *zodb.DB, treeRoot zod
}
}
ø
:=
PPTreeSubSet
{}
ø
:=
blib
.
PPTreeSubSet
{}
// trackSet1 = xkv1[tracked1]
// trackSet2 = xkv2[tracked2] ( = xkv2[kadj[tracked1]]
...
...
@@ -477,7 +473,7 @@ func xverifyΔBTail_Update1(t *testing.T, subj string, db *zodb.DB, treeRoot zod
// assert δtkeycov == δ(tkeyCov1, tkeyCov2)
δtkeycovOK
:=
tkeyCov2
.
Difference
(
tkeyCov1
)
δtkeycov
:=
&
RangedKeySet
{}
δtkeycov
:=
&
blib
.
RangedKeySet
{}
if
__
,
ok
:=
δB1
.
ByRoot
[
treeRoot
];
ok
{
δtkeycov
=
__
.
δtkeycov1
}
...
...
@@ -558,7 +554,7 @@ func xverifyΔBTail_Update1(t *testing.T, subj string, db *zodb.DB, treeRoot zod
// assertTrack verifies state of .trackSet and ΔTtail.trackNew.
// it assumes that only one tree root is being tracked.
// XXX place
func
(
δBtail
*
ΔBtail
)
assertTrack
(
t
*
testing
.
T
,
subj
string
,
trackSetOK
PPTreeSubSet
,
trackNewOK
PPTreeSubSet
)
{
func
(
δBtail
*
ΔBtail
)
assertTrack
(
t
*
testing
.
T
,
subj
string
,
trackSetOK
blib
.
PPTreeSubSet
,
trackNewOK
blib
.
PPTreeSubSet
)
{
t
.
Helper
()
if
!
δBtail
.
trackSet
.
Equal
(
trackSetOK
)
{
t
.
Errorf
(
"%s: trackSet:
\n\t
have: %v
\n\t
want: %v"
,
subj
,
δBtail
.
trackSet
,
trackSetOK
)
...
...
@@ -605,7 +601,7 @@ func (δBtail *ΔBtail) assertTrack(t *testing.T, subj string, trackSetOK PPTree
// t1->t2 further exercises incremental rebuild.
//
// It also exercises rebuild phase of ΔBtail.Update.
func
xverifyΔBTail_rebuild
(
t
*
testing
.
T
,
db
*
zodb
.
DB
,
treeRoot
zodb
.
Oid
,
t0
,
t1
,
t2
*
tTree
Commit
)
{
func
xverifyΔBTail_rebuild
(
t
*
testing
.
T
,
db
*
zodb
.
DB
,
treeRoot
zodb
.
Oid
,
t0
,
t1
,
t2
*
xbtreetest
.
Commit
)
{
t
.
Run
(
fmt
.
Sprintf
(
"rebuild/%s→%s"
,
t0
.
tree
,
t1
.
tree
),
func
(
t
*
testing
.
T
)
{
tAllKeys
:=
allTestKeys
(
t0
,
t1
,
t2
)
tAllKeyv
:=
tAllKeys
.
SortedElements
()
...
...
@@ -628,7 +624,7 @@ func xverifyΔBTail_rebuild(t *testing.T, db *zodb.DB, treeRoot zodb.Oid, t0, t1
// kadj210 = kadj10·kadj21
kadj210
:=
kadj10
.
Mul
(
kadj21
)
ø
:=
PPTreeSubSet
{}
ø
:=
blib
.
PPTreeSubSet
{}
// verify t0 -> t1 Track(keys1) Rebuild -> t2 Track(keys2) Rebuild
// for all combinations of keys1 and keys2
...
...
@@ -790,10 +786,10 @@ func xverifyΔBTail_rebuild(t *testing.T, db *zodb.DB, treeRoot zodb.Oid, t0, t1
}
// xverifyΔBTail_rebuild_U verifies ΔBtail state after Update(ti->tj).
func
xverifyΔBTail_rebuild_U
(
t
*
testing
.
T
,
δbtail
*
ΔBtail
,
treeRoot
zodb
.
Oid
,
ti
,
tj
*
tTreeCommit
,
xat
map
[
zodb
.
Tid
]
string
,
trackSet
PPTreeSubSet
,
vδTok
...
map
[
Key
]
Δstring
)
{
func
xverifyΔBTail_rebuild_U
(
t
*
testing
.
T
,
δbtail
*
ΔBtail
,
treeRoot
zodb
.
Oid
,
ti
,
tj
*
xbtreetest
.
Commit
,
xat
map
[
zodb
.
Tid
]
string
,
trackSet
blib
.
PPTreeSubSet
,
vδTok
...
map
[
Key
]
Δstring
)
{
t
.
Helper
()
X
:=
exc
.
Raiseif
ø
:=
PPTreeSubSet
{}
ø
:=
blib
.
PPTreeSubSet
{}
subj
:=
fmt
.
Sprintf
(
"after Update(@%s→@%s)"
,
xat
[
ti
.
at
],
xat
[
tj
.
at
])
...
...
@@ -835,9 +831,9 @@ func xverifyΔBTail_rebuild_U(t *testing.T, δbtail *ΔBtail, treeRoot zodb.Oid,
}
// xverifyΔBTail_rebuild_TR verifies ΔBtail state after Track(keys) + rebuild.
func
xverifyΔBTail_rebuild_TR
(
t
*
testing
.
T
,
δbtail
*
ΔBtail
,
tj
*
tTreeCommit
,
treeRoot
zodb
.
Oid
,
xat
map
[
zodb
.
Tid
]
string
,
keys
setKey
,
trackSet
PPTreeSubSet
,
trackNew
,
trackSetAfterRebuild
PPTreeSubSet
,
vδTok
...
map
[
Key
]
Δstring
)
{
func
xverifyΔBTail_rebuild_TR
(
t
*
testing
.
T
,
δbtail
*
ΔBtail
,
tj
*
xbtreetest
.
Commit
,
treeRoot
zodb
.
Oid
,
xat
map
[
zodb
.
Tid
]
string
,
keys
setKey
,
trackSet
blib
.
PPTreeSubSet
,
trackNew
,
trackSetAfterRebuild
blib
.
PPTreeSubSet
,
vδTok
...
map
[
Key
]
Δstring
)
{
t
.
Helper
()
ø
:=
PPTreeSubSet
{}
ø
:=
blib
.
PPTreeSubSet
{}
// Track(keys)
xtrackKeys
(
δbtail
,
tj
,
keys
)
...
...
@@ -858,14 +854,14 @@ func xverifyΔBTail_rebuild_TR(t *testing.T, δbtail *ΔBtail, tj *tTreeCommit,
// assertΔTtail verifies state of ΔTtail that corresponds to treeRoot in δbtail.
// it also verifies that δbtail.vδBroots matches ΔTtail data.
func
assertΔTtail
(
t
*
testing
.
T
,
subj
string
,
δbtail
*
ΔBtail
,
tj
*
tTree
Commit
,
treeRoot
zodb
.
Oid
,
xat
map
[
zodb
.
Tid
]
string
,
vδTok
...
map
[
Key
]
Δstring
)
{
func
assertΔTtail
(
t
*
testing
.
T
,
subj
string
,
δbtail
*
ΔBtail
,
tj
*
xbtreetest
.
Commit
,
treeRoot
zodb
.
Oid
,
xat
map
[
zodb
.
Tid
]
string
,
vδTok
...
map
[
Key
]
Δstring
)
{
t
.
Helper
()
// XXX +KVAtTail, +lastRevOf
l
:=
len
(
vδTok
)
var
vatOK
[]
zodb
.
Tid
var
vδTok_
[]
map
[
Key
]
Δstring
at2t
:=
map
[
zodb
.
Tid
]
*
tTree
Commit
{
tj
.
at
:
tj
}
at2t
:=
map
[
zodb
.
Tid
]
*
xbtreetest
.
Commit
{
tj
.
at
:
tj
}
t0
:=
tj
for
i
:=
0
;
i
<
l
;
i
++
{
// empty vδTok entries means they should be absent in vδT
...
...
@@ -933,7 +929,7 @@ func assertΔTtail(t *testing.T, subj string, δbtail *ΔBtail, tj *tTreeCommit,
// xtrackKeys issues δbtail.Track requests for tree[keys].
// XXX place
func
xtrackKeys
(
δbtail
*
ΔBtail
,
t
*
tTree
Commit
,
keys
setKey
)
{
func
xtrackKeys
(
δbtail
*
ΔBtail
,
t
*
xbtreetest
.
Commit
,
keys
setKey
)
{
X
:=
exc
.
Raiseif
head
:=
δbtail
.
Head
()
if
head
!=
t
.
at
{
...
...
@@ -960,7 +956,7 @@ func xtrackKeys(δbtail *ΔBtail, t *tTreeCommit, keys setKey) {
// XXX
// XXX kill
/*
func ___xverifyΔBTail_GetAt(t *testing.T, db *zodb.DB, treeRoot zodb.Oid, vt ...*
tTree
Commit) {
func ___xverifyΔBTail_GetAt(t *testing.T, db *zodb.DB, treeRoot zodb.Oid, vt ...*
xbtreetest.
Commit) {
subj := vt[0].tree
for _, t := range vt[1:] {
subj += "→" + t.tree
...
...
@@ -993,7 +989,7 @@ func ___xverifyΔBTail_GetAt(t *testing.T, db *zodb.DB, treeRoot zodb.Oid, vt ..
})
}
func xverifyΔBTail_GetAt1(t *testing.T, db *zodb.DB, treeRoot zodb.Oid, vt []*
tTree
Commit, xat map[zodb.Tid]string, keys setKey) {
func xverifyΔBTail_GetAt1(t *testing.T, db *zodb.DB, treeRoot zodb.Oid, vt []*
xbtreetest.
Commit, xat map[zodb.Tid]string, keys setKey) {
X := exc.Raiseif
// t1->t2-> ... -> tn
...
...
@@ -1081,9 +1077,9 @@ func ΔBTest(xtest interface{}) ΔBTestEntry {
// testΔBTail verifies ΔBTail on sequence of tree topologies coming from testq.
func
testΔBTail
(
t_
*
testing
.
T
,
testq
chan
ΔBTestEntry
)
{
t
:=
tNewTreeEnv
(
t_
)
t
:=
xbtreetest
.
NewT
(
t_
)
var
t0
*
tTree
Commit
var
t0
*
xbtreetest
.
Commit
for
test
:=
range
testq
{
t1
:=
t
.
Head
()
t2
:=
t
.
CommitTree
(
test
.
tree
)
...
...
@@ -1563,7 +1559,7 @@ func TestΔBTailAllStructs(t *testing.T) {
func
TestΔBtailForget
(
t_
*
testing
.
T
)
{
t
:=
tNewTreeEnv
(
t_
)
t
:=
xbtreetest
.
NewT
(
t_
)
X
:=
exc
.
Raiseif
t0
:=
t
.
CommitTree
(
"T/B:"
)
...
...
@@ -1602,7 +1598,7 @@ func TestΔBtailForget(t_ *testing.T) {
func
TestΔBtailClone
(
t_
*
testing
.
T
)
{
// ΔBtail.Clone had bug that aliased klon data to orig
t
:=
tNewTreeEnv
(
t_
)
t
:=
xbtreetest
.
NewT
(
t_
)
X
:=
exc
.
Raiseif
t0
:=
t
.
CommitTree
(
"T2/B1:a-B2:b"
)
...
...
@@ -1678,7 +1674,7 @@ func TestIntSets(t *testing.T) {
// allTestKeys returns all keys from vt + ∞.
func
allTestKeys
(
vt
...*
tTree
Commit
)
setKey
{
func
allTestKeys
(
vt
...*
xbtreetest
.
Commit
)
setKey
{
allKeys
:=
setKey
{};
allKeys
.
Add
(
KeyMax
)
// ∞ simulating ZBigFile.Size() query
for
_
,
t
:=
range
vt
{
for
_
,
b
:=
range
t
.
xkv
{
...
...
@@ -1738,34 +1734,3 @@ func δTEqual(δa, δb map[Key]Δstring) bool {
}
return
true
}
// ----------------------------------------
// ZBlk-related functions are imported at runtime by δbtail_x_test
var
(
ZTreeGetBlkData
func
(
context
.
Context
,
*
Tree
,
Key
)
(
string
,
bool
,
[]
Node
,
error
)
ZGetBlkData
func
(
context
.
Context
,
*
zodb
.
Connection
,
zodb
.
Oid
)
(
string
,
error
)
)
// xzgetBlkData loads block data from ZBlk object specified by its oid.
func
xzgetBlkData
(
ctx
context
.
Context
,
zconn
*
zodb
.
Connection
,
zblkOid
zodb
.
Oid
)
string
{
X
:=
exc
.
Raiseif
if
zblkOid
==
VDEL
{
return
DEL
}
data
,
err
:=
ZGetBlkData
(
ctx
,
zconn
,
zblkOid
);
X
(
err
)
return
string
(
data
)
}
// xzgetBlkDataAt loads block data from ZBlk object specified by oid@at.
func
xzgetBlkDataAt
(
db
*
zodb
.
DB
,
zblkOid
zodb
.
Oid
,
at
zodb
.
Tid
)
string
{
X
:=
exc
.
Raiseif
txn
,
ctx
:=
transaction
.
New
(
context
.
Background
())
defer
txn
.
Abort
()
zconn
,
err
:=
db
.
Open
(
ctx
,
&
zodb
.
ConnOptions
{
At
:
at
});
X
(
err
)
return
xzgetBlkData
(
ctx
,
zconn
,
zblkOid
)
}
wcfs/internal/xbtree/δbtail_x_test.go
View file @
11c95175
...
...
@@ -18,85 +18,7 @@
// See https://www.nexedi.com/licensing for rationale and options.
package
xbtree_test
// ZBlk-related part of δbtail_test
import
(
"context"
"fmt"
"lab.nexedi.com/kirr/go123/xerr"
"lab.nexedi.com/kirr/neo/go/zodb"
"lab.nexedi.com/nexedi/wendelin.core/wcfs/internal/xbtree"
"lab.nexedi.com/nexedi/wendelin.core/wcfs/internal/xzodb"
"lab.nexedi.com/nexedi/wendelin.core/wcfs/internal/zdata"
_
"lab.nexedi.com/nexedi/wendelin.core/wcfs/internal/xbtree/xbtreetest/init"
)
type
Tree
=
xbtree
.
Tree
type
Node
=
xbtree
.
Node
type
Key
=
xbtree
.
Key
type
ZBlk
=
zdata
.
ZBlk
// ztreeGetBlk returns ztree[k] and tree path that lead to this block.
// XXX +return blkRevMax and use it ?
func
ztreeGetBlk
(
ctx
context
.
Context
,
ztree
*
Tree
,
k
Key
)
(
zblk
ZBlk
,
ok
bool
,
path
[]
Node
,
err
error
)
{
path
=
[]
Node
{}
xzblk
,
ok
,
err
:=
ztree
.
VGet
(
ctx
,
k
,
func
(
node
Node
)
{
path
=
append
(
path
,
node
)
})
if
err
!=
nil
{
return
nil
,
false
,
nil
,
err
}
if
ok
{
zblk
,
ok
=
xzblk
.
(
ZBlk
)
if
!
ok
{
return
nil
,
false
,
nil
,
fmt
.
Errorf
(
"expect ZBlk*; got %s"
,
xzodb
.
TypeOf
(
xzblk
))
// XXX errctx
}
}
return
zblk
,
ok
,
path
,
nil
}
func
init
()
{
xbtree
.
ZTreeGetBlkData
=
ZTreeGetBlkData
xbtree
.
ZGetBlkData
=
ZGetBlkData
}
// ZTreeGetBlkData returns block data from block pointed to by ztree[k].
func
ZTreeGetBlkData
(
ctx
context
.
Context
,
ztree
*
Tree
,
k
Key
)
(
data
string
,
ok
bool
,
path
[]
Node
,
err
error
)
{
defer
xerr
.
Contextf
(
&
err
,
"@%s: tree<%s>: get blkdata from [%d]"
,
ztree
.
PJar
()
.
At
(),
ztree
.
POid
(),
k
)
zblk
,
ok
,
path
,
err
:=
ztreeGetBlk
(
ctx
,
ztree
,
k
)
if
err
!=
nil
||
!
ok
{
return
""
,
ok
,
path
,
err
}
bdata
,
_
,
err
:=
zblk
.
LoadBlkData
(
ctx
)
if
err
!=
nil
{
return
""
,
false
,
nil
,
err
}
return
string
(
bdata
),
true
,
path
,
nil
}
// ZGetBlkData loads block data from ZBlk object specified by its oid.
func
ZGetBlkData
(
ctx
context
.
Context
,
zconn
*
zodb
.
Connection
,
zblkOid
zodb
.
Oid
)
(
data
string
,
err
error
)
{
defer
xerr
.
Contextf
(
&
err
,
"@%s: get blkdata from obj %s"
,
zconn
.
At
(),
zblkOid
)
xblk
,
err
:=
zconn
.
Get
(
ctx
,
zblkOid
)
if
err
!=
nil
{
return
""
,
err
}
zblk
,
ok
:=
xblk
.
(
ZBlk
)
if
!
ok
{
return
""
,
fmt
.
Errorf
(
"expect ZBlk*; got %s"
,
xzodb
.
TypeOf
(
xblk
))
}
bdata
,
_
,
err
:=
zblk
.
LoadBlkData
(
ctx
)
if
err
!=
nil
{
return
""
,
err
}
return
string
(
bdata
),
nil
}
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