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
4f4592cb
Commit
4f4592cb
authored
Jan 24, 2019
by
Kirill Smelkov
Browse files
Options
Browse Files
Download
Email Patches
Plain Diff
.
parent
ae34d7bc
Changes
5
Hide whitespace changes
Inline
Side-by-side
Showing
5 changed files
with
30 additions
and
366 deletions
+30
-366
wcfs/gen-δtail
wcfs/gen-δtail
+9
-5
wcfs/zset_i64.go
wcfs/zset_i64.go
+1
-1
wcfs/zδtail_i64.go
wcfs/zδtail_i64.go
+20
-7
wcfs/δtail.go.in
wcfs/δtail.go.in
+0
-189
wcfs/δtail_test.go
wcfs/δtail_test.go
+0
-164
No files found.
wcfs/gen-δtail
View file @
4f4592cb
...
@@ -25,13 +25,17 @@ KIND=$1
...
@@ -25,13 +25,17 @@ KIND=$1
ID
=
$2
ID
=
$2
out
=
$3
out
=
$3
input
=
$(
dirname
$0
)
/δtail.go.in
zodb
=
lab.nexedi.com/kirr/neo/go/zodb
zdir
=
`
go list
-f
'{{.Dir}}'
$zodb
`
zrev
=
`
git
-C
$zdir
describe
--always
`
echo
"// Code generated by gen-δtail
$KIND
$ID
; DO NOT EDIT."
>
$out
echo
"// Code generated by gen-δtail
$KIND
$ID
; DO NOT EDIT."
>
$out
echo
"// (from
$zodb
@
$zrev
)"
>>
$out
echo
>>
$out
echo
>>
$out
sed
\
$zdir
/δtail.go.cat-generic |
sed
\
-e
"s/ID/
$ID
/g"
\
-e
"s/PACKAGE/main/g"
\
-e
"s/ΔTail/ΔTail
${
KIND
}
/g"
\
-e
"s/ID/
$ID
/g"
\
-e
"s/ΔTail/ΔTail
${
KIND
}
/g"
\
-e
"s/δRevEntry/δRevEntry
${
KIND
}
/g"
\
-e
"s/δRevEntry/δRevEntry
${
KIND
}
/g"
\
$input
>>
$out
>>
$out
wcfs/zset_i64.go
View file @
4f4592cb
// Code generated by gen-set I64 int64; DO NOT EDIT.
// Code generated by gen-set I64 int64; DO NOT EDIT.
// Copyright (C) 2015-201
8
Nexedi SA and Contributors.
// Copyright (C) 2015-201
9
Nexedi SA and Contributors.
// Kirill Smelkov <kirr@nexedi.com>
// Kirill Smelkov <kirr@nexedi.com>
//
//
// This program is free software: you can Use, Study, Modify and Redistribute
// This program is free software: you can Use, Study, Modify and Redistribute
...
...
wcfs/zδtail_i64.go
View file @
4f4592cb
// Code generated by gen-δtail I64 int64; DO NOT EDIT.
// Code generated by gen-δtail I64 int64; DO NOT EDIT.
// (from lab.nexedi.com/kirr/neo/go/zodb @ v1.9-2078-gae3c4829)
// Copyright (C) 2018 Nexedi SA and Contributors.
// Copyright (C) 2018
-2019
Nexedi SA and Contributors.
// Kirill Smelkov <kirr@nexedi.com>
//
Kirill Smelkov <kirr@nexedi.com>
//
//
// This program is free software: you can Use, Study, Modify and Redistribute
// 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
// it under the terms of the GNU General Public License version 3, or (at your
...
@@ -21,18 +22,25 @@
...
@@ -21,18 +22,25 @@
package
main
package
main
import
"lab.nexedi.com/kirr/neo/go/zodb"
import
(
import
(
"fmt"
"fmt"
"lab.nexedi.com/kirr/neo/go/zodb"
)
)
// XXX do we really need ΔTailI64 to be exported from zodb?
// (other users are low level caches + maybe ZEO/NEO -> zplumbing? but then import cycle)
// ΔTailI64 represents tail of revisional changes.
// ΔTailI64 represents tail of revisional changes.
//
//
// It semantically consists of
// It semantically consists of
//
//
// [](rev↑, []id)
// [](rev↑, []id)
//
//
// and index
//
// {} id -> max(rev: rev changed id)
//
// where
// where
//
//
// rev - is ZODB revision, and
// rev - is ZODB revision, and
...
@@ -40,12 +48,12 @@ import (
...
@@ -40,12 +48,12 @@ import (
//
//
// It provides operations to
// It provides operations to
//
//
// - XXX Head
// - append information to the tail about next revision,
// - append information to the tail about next revision,
// - forget information in the tail past specified revision, and
// - forget information in the tail past specified revision, and
// - query the tail about what is last revision that changed an id.
// - query the tail about what is last revision that changed an id.
//
//
// It is generally not safe to use ΔTailI64 from multiple goroutines simultaneously.
// ΔTailI64 is safe to access for multiple-readers / single writer.
// It is safe to perform multiple simultaneous read-kind operations.
//
//
// (*) examples of id:
// (*) examples of id:
//
//
...
@@ -56,7 +64,7 @@ type ΔTailI64 struct {
...
@@ -56,7 +64,7 @@ type ΔTailI64 struct {
lastRevOf
map
[
int64
]
zodb
.
Tid
// index for LastRevOf queries
lastRevOf
map
[
int64
]
zodb
.
Tid
// index for LastRevOf queries
// TODO also add either tailv idx <-> rev index, or lastRevOf -> tailv idx
// TODO also add either tailv idx <-> rev index, or lastRevOf -> tailv idx
// (if linear back-scan of δRevEntryI64 starts eat cpu).
// (if linear back-scan of δRevEntryI64 starts
to
eat cpu).
}
}
// δRevEntryI64 represents information of what have been changed in one revision.
// δRevEntryI64 represents information of what have been changed in one revision.
...
@@ -70,6 +78,11 @@ func NewΔTailI64() *ΔTailI64 {
...
@@ -70,6 +78,11 @@ func NewΔTailI64() *ΔTailI64 {
return
&
ΔTailI64
{
lastRevOf
:
make
(
map
[
int64
]
zodb
.
Tid
)}
return
&
ΔTailI64
{
lastRevOf
:
make
(
map
[
int64
]
zodb
.
Tid
)}
}
}
// XXX + .Head() -> max(rev) XXX or 0 if len(tailv) == 0?
func
(
δtail
*
ΔTailI64
)
Head
()
zodb
.
Tid
{
panic
(
"TODO"
)
}
// XXX add way to extend coverage without appending changed data? (i.e. if a
// XXX add way to extend coverage without appending changed data? (i.e. if a
// txn did not change file at all) -> but then it is simply .Append(rev, nil)?
// txn did not change file at all) -> but then it is simply .Append(rev, nil)?
...
...
wcfs/δtail.go.in
deleted
100644 → 0
View file @
ae34d7bc
//
Copyright
(
C
)
2018
-
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
main
import
(
"fmt"
"lab.nexedi.com/kirr/neo/go/zodb"
)
//
Δ
Tail
represents
tail
of
revisional
changes
.
//
//
It
semantically
consists
of
//
//
[](
rev
↑
,
[]
id
)
//
//
and
index
//
//
{}
id
->
max
(
rev
:
rev
changed
id
)
//
//
where
//
//
rev
-
is
ZODB
revision
,
and
//
id
-
is
an
identifier
of
what
has
been
changed
(*)
//
//
It
provides
operations
to
//
//
-
append
information
to
the
tail
about
next
revision
,
//
-
forget
information
in
the
tail
past
specified
revision
,
and
//
-
query
the
tail
about
what
is
last
revision
that
changed
an
id
.
//
//
Δ
Tail
is
safe
to
access
for
multiple
-
readers
/
single
writer
.
//
//
(*)
examples
of
id
:
//
//
oid
-
ZODB
object
identifier
,
when
Δ
Tail
represents
changes
to
ZODB
objects
,
//
#
blk
-
file
block
number
,
when
Δ
Tail
represents
changes
to
a
file
.
type
Δ
Tail
struct
{
tailv
[]
δ
RevEntry
lastRevOf
map
[
ID
]
zodb
.
Tid
//
index
for
LastRevOf
queries
//
TODO
also
add
either
tailv
idx
<->
rev
index
,
or
lastRevOf
->
tailv
idx
//
(
if
linear
back
-
scan
of
δ
RevEntry
starts
to
eat
cpu
).
}
//
δ
RevEntry
represents
information
of
what
have
been
changed
in
one
revision
.
type
δ
RevEntry
struct
{
rev
zodb
.
Tid
changev
[]
ID
}
//
New
Δ
Tail
creates
new
Δ
Tail
object
.
func
New
Δ
Tail
()
*
Δ
Tail
{
return
&
Δ
Tail
{
lastRevOf
:
make
(
map
[
ID
]
zodb
.
Tid
)}
}
//
XXX
+
.
Head
()
->
max
(
rev
)
XXX
or
0
if
len
(
tailv
)
==
0
?
//
XXX
add
way
to
extend
coverage
without
appending
changed
data
?
(
i
.
e
.
if
a
//
txn
did
not
change
file
at
all
)
->
but
then
it
is
simply
.
Append
(
rev
,
nil
)?
//
Append
appends
to
δ
tail
information
about
what
have
been
changed
in
next
revision
.
//
//
rev
must
be
↑
.
func
(
δ
tail
*
Δ
Tail
)
Append
(
rev
zodb
.
Tid
,
changev
[]
ID
)
{
//
check
rev
↑
//
XXX
better
also
check
even
when
δ
tail
is
ø
(
after
forget
)
if
l
:=
len
(
δ
tail
.
tailv
);
l
>
0
{
if
revPrev
:=
δ
tail
.
tailv
[
l
-
1
].
rev
;
revPrev
>=
rev
{
panic
(
fmt
.
Sprintf
(
"δtail.Append: rev not ↑: %s -> %s"
,
revPrev
,
rev
))
}
}
δ
tail
.
tailv
=
append
(
δ
tail
.
tailv
,
δ
RevEntry
{
rev
,
changev
})
for
_
,
id
:=
range
changev
{
δ
tail
.
lastRevOf
[
id
]
=
rev
}
}
//
ForgetBefore
discards
all
δ
tail
entries
with
rev
<
revCut
.
func
(
δ
tail
*
Δ
Tail
)
ForgetBefore
(
revCut
zodb
.
Tid
)
{
icut
:=
0
for
i
,
δ
:=
range
δ
tail
.
tailv
{
rev
:=
δ
.
rev
if
rev
>=
revCut
{
break
}
icut
=
i
+
1
//
if
forgotten
revision
was
last
for
id
,
we
have
to
update
lastRevOf
index
for
_
,
id
:=
range
δ
.
changev
{
if
δ
tail
.
lastRevOf
[
id
]
==
rev
{
delete
(
δ
tail
.
lastRevOf
,
id
)
}
}
}
//
tailv
=
tailv
[
icut
:]
but
without
//
1
)
growing
underlying
storage
array
indefinitely
//
2
)
keeping
underlying
storage
after
forget
l
:=
len
(
δ
tail
.
tailv
)-
icut
tailv
:=
make
([]
δ
RevEntry
,
l
)
copy
(
tailv
,
δ
tail
.
tailv
[
icut
:])
δ
tail
.
tailv
=
tailv
}
//
LastRevOf
tries
to
return
what
was
the
last
revision
that
changed
id
as
of
at
database
state
.
//
//
Depending
on
current
information
in
δ
tail
it
returns
either
exact
result
,
or
//
an
upper
-
bound
estimate
for
the
last
id
revision
,
assuming
id
was
changed
≤
at
:
//
//
1
)
if
δ
tail
does
not
cover
at
,
at
is
returned
:
//
//
#
at
∉
[
min
(
rev
∈
δ
tail
),
max
(
rev
∈
δ
tail
)]
//
LastRevOf
(
id
,
at
)
=
at
//
//
2
)
if
δ
tail
has
an
entry
corresponding
to
id
change
,
it
gives
exactly
the
//
last
revision
that
changed
id
:
//
//
#
at
∈
[
min
(
rev
∈
δ
tail
),
max
(
rev
∈
δ
tail
)]
//
#
∃
rev
∈
δ
tail
:
rev
changed
id
&&
rev
≤
at
//
LastRevOf
(
id
,
at
)
=
max
(
rev
:
rev
changed
id
&&
rev
≤
at
)
//
//
3
)
if
δ
tail
does
not
contain
appropriate
record
with
id
-
it
returns
δ
tail
's
// lower bound as the estimate for the upper bound of the last id revision:
//
// # at ∈ [min(rev ∈ δtail), max(rev ∈ δtail)]
// # ∄ rev ∈ δtail: rev changed id && rev ≤ at
// LastRevOf(id, at) = min(rev ∈ δtail)
//
// On return exact indicates whether returned revision is exactly the last
// revision of id, or only an upper-bound estimate of it.
func (δtail *ΔTail) LastRevOf(id ID, at zodb.Tid) (_ zodb.Tid, exact bool) {
// check if we have no coverage at all
l := len(δtail.tailv)
if l == 0 {
return at, false
}
revMin := δtail.tailv[0].rev
revMax := δtail.tailv[l-1].rev
if !(revMin <= at && at <= revMax) {
return at, false
}
// we have the coverage
rev, ok := δtail.lastRevOf[id]
if !ok {
return δtail.tailv[0].rev, false
}
if rev <= at {
return rev, true
}
// what'
s
in
index
is
after
at
-
scan
tailv
back
to
find
appropriate
entry
//
XXX
linear
scan
for
i
:=
l
-
1
;
i
>=
0
;
i
--
{
δ
:=
δ
tail
.
tailv
[
i
]
if
δ
.
rev
>
at
{
continue
}
for
_
,
δ
id
:=
range
δ
.
changev
{
if
id
==
δ
id
{
return
δ
.
rev
,
true
}
}
}
//
nothing
found
return
δ
tail
.
tailv
[
0
].
rev
,
false
}
wcfs/δtail_test.go
deleted
100644 → 0
View file @
ae34d7bc
// Copyright (C) 2018-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
main
import
(
"fmt"
"reflect"
"testing"
"lab.nexedi.com/kirr/neo/go/zodb"
)
func
TestΔTail
(
t
*
testing
.
T
)
{
δtail
:=
NewΔTailI64
()
// R is syntactic sugar to create 1 δRevEntry
R
:=
func
(
rev
zodb
.
Tid
,
changev
...
int64
)
δRevEntryI64
{
return
δRevEntryI64
{
rev
,
changev
}
}
// δAppend is syntactic sugar for δtail.Append
δAppend
:=
func
(
δ
δRevEntryI64
)
{
δtail
.
Append
(
δ
.
rev
,
δ
.
changev
)
}
// δCheck verifies that δtail state corresponds to provided tailv
δCheck
:=
func
(
tailv
...
δRevEntryI64
)
{
t
.
Helper
()
for
i
:=
1
;
i
<
len
(
tailv
);
i
++
{
if
!
(
tailv
[
i
-
1
]
.
rev
<
tailv
[
i
]
.
rev
)
{
panic
(
"test tailv: rev not ↑"
)
}
}
if
!
tailvEqual
(
δtail
.
tailv
,
tailv
)
{
t
.
Fatalf
(
"tailv:
\n
have: %v
\n
want: %v"
,
δtail
.
tailv
,
tailv
)
}
// verify lastRevOf query / index
lastRevOf
:=
make
(
map
[
int64
]
zodb
.
Tid
)
for
_
,
δ
:=
range
tailv
{
for
_
,
id
:=
range
δ
.
changev
{
idRev
,
exact
:=
δtail
.
LastRevOf
(
id
,
δ
.
rev
)
if
!
(
idRev
==
δ
.
rev
&&
exact
)
{
t
.
Fatalf
(
"LastRevOf(%v, at=%s) -> %s, %v ; want %s, %v"
,
id
,
δ
.
rev
,
idRev
,
exact
,
δ
.
rev
,
true
)
}
lastRevOf
[
id
]
=
δ
.
rev
}
}
if
!
reflect
.
DeepEqual
(
δtail
.
lastRevOf
,
lastRevOf
)
{
t
.
Fatalf
(
"lastRevOf:
\n
have: %v
\n
want: %v"
,
δtail
.
lastRevOf
,
lastRevOf
)
}
}
// δCheckLastUP verifies that δtail.LastRevOf(id, at) gives lastOk and exact=false.
// (we don't need to check for exact=true as those cases are covered in δCheck)
δCheckLastUP
:=
func
(
id
int64
,
at
,
lastOk
zodb
.
Tid
)
{
t
.
Helper
()
last
,
exact
:=
δtail
.
LastRevOf
(
id
,
at
)
if
!
(
last
==
lastOk
&&
exact
==
false
)
{
t
.
Fatalf
(
"LastRevOf(%v, at=%s) -> %s, %v ; want %s, %v"
,
id
,
at
,
last
,
exact
,
lastOk
,
false
)
}
}
δCheck
()
δCheckLastUP
(
4
,
12
,
12
)
// δtail = ø
δAppend
(
R
(
10
,
3
,
5
))
δCheck
(
R
(
10
,
3
,
5
))
δCheckLastUP
(
3
,
9
,
9
)
// at < δtail
δCheckLastUP
(
3
,
12
,
12
)
// at > δtail
δCheckLastUP
(
4
,
10
,
10
)
// id ∉ δtail
δAppend
(
R
(
11
,
7
))
δCheck
(
R
(
10
,
3
,
5
),
R
(
11
,
7
))
δAppend
(
R
(
12
,
7
))
δCheck
(
R
(
10
,
3
,
5
),
R
(
11
,
7
),
R
(
12
,
7
))
δAppend
(
R
(
14
,
3
,
8
))
δCheck
(
R
(
10
,
3
,
5
),
R
(
11
,
7
),
R
(
12
,
7
),
R
(
14
,
3
,
8
))
δCheckLastUP
(
8
,
12
,
10
)
// id ∈ δtail, but has no entry with rev ≤ at
δtail
.
ForgetBefore
(
10
)
δCheck
(
R
(
10
,
3
,
5
),
R
(
11
,
7
),
R
(
12
,
7
),
R
(
14
,
3
,
8
))
δtail
.
ForgetBefore
(
11
)
δCheck
(
R
(
11
,
7
),
R
(
12
,
7
),
R
(
14
,
3
,
8
))
δtail
.
ForgetBefore
(
13
)
δCheck
(
R
(
14
,
3
,
8
))
δtail
.
ForgetBefore
(
15
)
δCheck
()
// Append panics on non-↑ rev
δAppend
(
R
(
15
,
1
))
func
()
{
defer
func
()
{
r
:=
recover
()
if
r
==
nil
{
t
.
Fatal
(
"append non-↑: not panicked"
)
}
rev
:=
zodb
.
Tid
(
15
)
want
:=
fmt
.
Sprintf
(
"δtail.Append: rev not ↑: %s -> %s"
,
rev
,
rev
)
if
r
!=
want
{
t
.
Fatalf
(
"append non-↑:
\n
have: %q
\n
want: %q"
,
r
,
want
)
}
}()
δAppend
(
R
(
15
,
1
))
}()
// .tailv underlying storage is not kept after forget
δtail
.
ForgetBefore
(
16
)
const
N
=
1E3
for
rev
,
i
:=
zodb
.
Tid
(
16
),
0
;
i
<
N
;
i
,
rev
=
i
+
1
,
rev
+
1
{
δAppend
(
R
(
rev
,
1
))
}
capN
:=
cap
(
δtail
.
tailv
)
δtail
.
ForgetBefore
(
N
)
if
c
:=
cap
(
δtail
.
tailv
);
!
(
c
<
capN
/
10
)
{
t
.
Fatalf
(
"forget: tailv storage did not shrink: cap%v: %d -> cap: %d"
,
N
,
capN
,
c
)
}
// .tailv underlying storage does not grow indefinitely
// XXX cannot test as the growth here goes to left and we cannot get
// access to whole underlying array from a slice.
}
func
tailvEqual
(
a
,
b
[]
δRevEntryI64
)
bool
{
// for empty one can be nil and another !nil [] = reflect.DeepEqual
// does not think those are equal.
return
(
len
(
a
)
==
0
&&
len
(
b
)
==
0
)
||
reflect
.
DeepEqual
(
a
,
b
)
}
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