Skip to content
Projects
Groups
Snippets
Help
Loading...
Help
Support
Keyboard shortcuts
?
Submit feedback
Contribute to GitLab
Sign in / Register
Toggle navigation
N
neoppod
Project overview
Project overview
Details
Activity
Releases
Repository
Repository
Files
Commits
Branches
Tags
Contributors
Graph
Compare
Issues
1
Issues
1
List
Boards
Labels
Milestones
Merge Requests
2
Merge Requests
2
CI / CD
CI / CD
Pipelines
Jobs
Schedules
Analytics
Analytics
CI / CD
Repository
Value Stream
Snippets
Snippets
Members
Members
Collapse sidebar
Close sidebar
Activity
Graph
Create a new issue
Jobs
Commits
Issue Boards
Open sidebar
nexedi
neoppod
Commits
375efa1e
Commit
375efa1e
authored
Nov 08, 2017
by
Kirill Smelkov
Browse files
Options
Browse Files
Download
Email Patches
Plain Diff
.
parent
f44b8da3
Changes
4
Hide whitespace changes
Inline
Side-by-side
Showing
4 changed files
with
74 additions
and
74 deletions
+74
-74
go/zodb/storage/fs1/filestorage.go
go/zodb/storage/fs1/filestorage.go
+1
-2
go/zodb/storage/fs1/format.go
go/zodb/storage/fs1/format.go
+68
-70
go/zodb/storage/fs1/fs1tools/dump.go
go/zodb/storage/fs1/fs1tools/dump.go
+3
-1
go/zodb/storage/fs1/py/gen-testdata
go/zodb/storage/fs1/py/gen-testdata
+2
-1
No files found.
go/zodb/storage/fs1/filestorage.go
View file @
375efa1e
...
@@ -124,14 +124,13 @@ func (e *ErrXidLoad) Error() string {
...
@@ -124,14 +124,13 @@ func (e *ErrXidLoad) Error() string {
}
}
// freelist(DataHeader)
XXX move -> format.go ?
// freelist(DataHeader)
var
dhPool
=
sync
.
Pool
{
New
:
func
()
interface
{}
{
return
&
DataHeader
{}
}}
var
dhPool
=
sync
.
Pool
{
New
:
func
()
interface
{}
{
return
&
DataHeader
{}
}}
// DataHeaderAlloc allocates DataHeader from freelist.
// DataHeaderAlloc allocates DataHeader from freelist.
func
DataHeaderAlloc
()
*
DataHeader
{
func
DataHeaderAlloc
()
*
DataHeader
{
return
dhPool
.
Get
()
.
(
*
DataHeader
)
return
dhPool
.
Get
()
.
(
*
DataHeader
)
}
}
// Free puts dh back into DataHeader freelist.
// Free puts dh back into DataHeader freelist.
//
//
// Caller must not use dh after call to Free.
// Caller must not use dh after call to Free.
...
...
go/zodb/storage/fs1/format.go
View file @
375efa1e
...
@@ -87,61 +87,56 @@ const (
...
@@ -87,61 +87,56 @@ const (
lenIterStart
int64
=
-
0x1111111111111112
// = 0xeeeeeeeeeeeeeeee if unsigned
lenIterStart
int64
=
-
0x1111111111111112
// = 0xeeeeeeeeeeeeeeee if unsigned
)
)
// TxnError is returned on transaction record read / decode errors
// RecordError represents error associated with operation on a record in
type
TxnError
struct
{
// FileStorage data file.
Pos
int64
// position of transaction record
type
RecordError
struct
{
Subj
string
// about what .Err is
Path
string
// path of the data file
Record
string
// record kind - "file header", "transaction record", "data record", ...
Pos
int64
// position of record
Subj
string
// subject context for the error - e.g. "read", "check" or "bug"
Err
error
// actual error
Err
error
// actual error
}
}
func
(
e
*
TxnError
)
Error
()
string
{
func
(
e
*
RecordError
)
Cause
()
error
{
return
fmt
.
Sprintf
(
"transaction record @%v: %v: %v"
,
e
.
Pos
,
e
.
Subj
,
e
.
Err
)
return
e
.
Err
}
}
// err creates TxnError for transaction located at txnh.Pos
func
(
e
*
RecordError
)
Error
()
string
{
func
(
txnh
*
TxnHeader
)
err
(
subj
string
,
err
error
)
error
{
// XXX omit path: when .Err already contains it (e.g. when it is os.PathError)?
return
&
TxnError
{
txnh
.
Pos
,
subj
,
err
}
return
fmt
.
Sprintf
(
"%s: %s @%d: %s: %s"
,
e
.
Path
,
e
.
Record
,
e
.
Pos
,
e
.
Subj
,
e
.
Err
)
}
}
// err creates RecordError for transaction located at txnh.Pos
// DataError is returned on data record read / decode errors
func
(
txnh
*
TxnHeader
)
err
(
r
io
.
ReaderAt
,
subj
string
,
err
error
)
error
{
type
DataError
struct
{
return
&
RecordError
{
xio
.
Name
(
r
),
"transaction record"
,
txnh
.
Pos
,
subj
,
err
}
Pos
int64
// position of data record
Subj
string
// about what .Err is
Err
error
// actual error
}
}
func
(
e
*
DataError
)
Error
()
string
{
return
fmt
.
Sprintf
(
"data record @%v: %v: %v"
,
e
.
Pos
,
e
.
Subj
,
e
.
Err
)
}
// err creates DataError for data record located at dh.Pos
// err creates RecordError for data record located at dh.Pos
//
func
(
dh
*
DataHeader
)
err
(
r
io
.
ReaderAt
,
subj
string
,
err
error
)
error
{
// XXX add link to containing txn? (check whether we can do it on data access) ?
return
&
RecordError
{
xio
.
Name
(
r
),
"data record"
,
dh
.
Pos
,
subj
,
err
}
func
(
dh
*
DataHeader
)
err
(
subj
string
,
err
error
)
error
{
return
&
DataError
{
dh
.
Pos
,
subj
,
err
}
}
}
// ierr is an interface for something which can create errors.
// ierr is an interface for something which can create errors.
// it is used by TxnHeader and DataHeader to create appropriate errors with their context.
// it is used by TxnHeader and DataHeader to create appropriate errors with their context.
type
ierr
interface
{
type
ierr
interface
{
err
(
subj
string
,
err
error
)
error
err
(
r
io
.
ReaderAt
,
subj
string
,
err
error
)
error
}
}
// errf is syntactic shortcut for err and fmt.Errorf
// errf is syntactic shortcut for err and fmt.Errorf
func
errf
(
e
ierr
,
subj
,
format
string
,
a
...
interface
{})
error
{
func
errf
(
r
io
.
ReaderAt
,
e
ierr
,
subj
,
format
string
,
a
...
interface
{})
error
{
return
e
.
err
(
subj
,
fmt
.
Errorf
(
format
,
a
...
))
return
e
.
err
(
r
,
subj
,
fmt
.
Errorf
(
format
,
a
...
))
}
}
// checkErr is syntactic shortcut for errf("check", ...)
// checkErr is syntactic shortcut for errf("check", ...)
func
checkErr
(
e
ierr
,
format
string
,
a
...
interface
{})
error
{
func
checkErr
(
r
io
.
ReaderAt
,
e
ierr
,
format
string
,
a
...
interface
{})
error
{
return
errf
(
e
,
"check"
,
format
,
a
...
)
return
errf
(
r
,
e
,
"check"
,
format
,
a
...
)
}
}
// bug panics with errf("bug", ...)
// bug panics with errf("bug", ...)
func
bug
(
e
ierr
,
format
string
,
a
...
interface
{})
{
func
bug
(
r
io
.
ReaderAt
,
e
ierr
,
format
string
,
a
...
interface
{})
{
panic
(
errf
(
e
,
"bug"
,
format
,
a
...
))
panic
(
errf
(
r
,
e
,
"bug"
,
format
,
a
...
))
}
}
...
@@ -236,7 +231,7 @@ func (txnh *TxnHeader) Load(r io.ReaderAt, pos int64, flags TxnLoadFlags) error
...
@@ -236,7 +231,7 @@ func (txnh *TxnHeader) Load(r io.ReaderAt, pos int64, flags TxnLoadFlags) error
txnh
.
LenPrev
=
0
// read error
txnh
.
LenPrev
=
0
// read error
if
pos
<
txnValidFrom
{
if
pos
<
txnValidFrom
{
bug
(
txnh
,
"Load() on invalid position"
)
bug
(
r
,
txnh
,
"Load() on invalid position"
)
}
}
var
n
int
var
n
int
...
@@ -249,14 +244,14 @@ func (txnh *TxnHeader) Load(r io.ReaderAt, pos int64, flags TxnLoadFlags) error
...
@@ -249,14 +244,14 @@ func (txnh *TxnHeader) Load(r io.ReaderAt, pos int64, flags TxnLoadFlags) error
if
n
>=
0
{
if
n
>=
0
{
lenPrev
:=
8
+
int64
(
binary
.
BigEndian
.
Uint64
(
work
[
8
-
8
:
]))
lenPrev
:=
8
+
int64
(
binary
.
BigEndian
.
Uint64
(
work
[
8
-
8
:
]))
if
lenPrev
<
TxnHeaderFixSize
{
if
lenPrev
<
TxnHeaderFixSize
{
return
checkErr
(
txnh
,
"invalid prev record length: %v"
,
lenPrev
)
return
checkErr
(
r
,
txnh
,
"invalid prev record length: %v"
,
lenPrev
)
}
}
posPrev
:=
txnh
.
Pos
-
lenPrev
posPrev
:=
txnh
.
Pos
-
lenPrev
if
posPrev
<
txnValidFrom
{
if
posPrev
<
txnValidFrom
{
return
checkErr
(
txnh
,
"prev record length goes beyond valid area: %v"
,
lenPrev
)
return
checkErr
(
r
,
txnh
,
"prev record length goes beyond valid area: %v"
,
lenPrev
)
}
}
if
posPrev
<
txnValidFrom
+
TxnHeaderFixSize
&&
posPrev
!=
txnValidFrom
{
if
posPrev
<
txnValidFrom
+
TxnHeaderFixSize
&&
posPrev
!=
txnValidFrom
{
return
checkErr
(
txnh
,
"prev record does not land exactly at valid area start: %v"
,
posPrev
)
return
checkErr
(
r
,
txnh
,
"prev record does not land exactly at valid area start: %v"
,
posPrev
)
}
}
txnh
.
LenPrev
=
lenPrev
txnh
.
LenPrev
=
lenPrev
}
}
...
@@ -275,24 +270,24 @@ func (txnh *TxnHeader) Load(r io.ReaderAt, pos int64, flags TxnLoadFlags) error
...
@@ -275,24 +270,24 @@ func (txnh *TxnHeader) Load(r io.ReaderAt, pos int64, flags TxnLoadFlags) error
// EOF after txn header is not good - because at least
// EOF after txn header is not good - because at least
// redundant length should be also there
// redundant length should be also there
return
txnh
.
err
(
"read"
,
noEOF
(
err
))
return
txnh
.
err
(
r
,
"read"
,
noEOF
(
err
))
}
}
txnh
.
Tid
=
zodb
.
Tid
(
binary
.
BigEndian
.
Uint64
(
work
[
8
+
0
:
]))
txnh
.
Tid
=
zodb
.
Tid
(
binary
.
BigEndian
.
Uint64
(
work
[
8
+
0
:
]))
if
!
txnh
.
Tid
.
Valid
()
{
if
!
txnh
.
Tid
.
Valid
()
{
return
checkErr
(
txnh
,
"invalid tid: %v"
,
txnh
.
Tid
)
return
checkErr
(
r
,
txnh
,
"invalid tid: %v"
,
txnh
.
Tid
)
}
}
tlen
:=
8
+
int64
(
binary
.
BigEndian
.
Uint64
(
work
[
8
+
8
:
]))
tlen
:=
8
+
int64
(
binary
.
BigEndian
.
Uint64
(
work
[
8
+
8
:
]))
if
tlen
<
TxnHeaderFixSize
{
if
tlen
<
TxnHeaderFixSize
{
return
checkErr
(
txnh
,
"invalid txn record length: %v"
,
tlen
)
return
checkErr
(
r
,
txnh
,
"invalid txn record length: %v"
,
tlen
)
}
}
// XXX also check tlen to not go beyond file size ?
// XXX also check tlen to not go beyond file size ?
// txnh.Len will be set =tlen at last - after checking other fields for correctness.
// txnh.Len will be set =tlen at last - after checking other fields for correctness.
txnh
.
Status
=
zodb
.
TxnStatus
(
work
[
8
+
16
])
txnh
.
Status
=
zodb
.
TxnStatus
(
work
[
8
+
16
])
if
!
txnh
.
Status
.
Valid
()
{
if
!
txnh
.
Status
.
Valid
()
{
return
checkErr
(
txnh
,
"invalid status: %q"
,
txnh
.
Status
)
return
checkErr
(
r
,
txnh
,
"invalid status: %q"
,
txnh
.
Status
)
}
}
...
@@ -302,7 +297,7 @@ func (txnh *TxnHeader) Load(r io.ReaderAt, pos int64, flags TxnLoadFlags) error
...
@@ -302,7 +297,7 @@ func (txnh *TxnHeader) Load(r io.ReaderAt, pos int64, flags TxnLoadFlags) error
lstr
:=
int
(
luser
)
+
int
(
ldesc
)
+
int
(
lext
)
lstr
:=
int
(
luser
)
+
int
(
ldesc
)
+
int
(
lext
)
if
TxnHeaderFixSize
+
int64
(
lstr
)
+
8
>
tlen
{
if
TxnHeaderFixSize
+
int64
(
lstr
)
+
8
>
tlen
{
return
checkErr
(
txnh
,
"strings overlap with txn boundary: %v / %v"
,
lstr
,
tlen
)
return
checkErr
(
r
,
txnh
,
"strings overlap with txn boundary: %v / %v"
,
lstr
,
tlen
)
}
}
// set .Len at last after doing all header checks
// set .Len at last after doing all header checks
...
@@ -338,7 +333,7 @@ func (txnh *TxnHeader) loadStrings(r io.ReaderAt) error {
...
@@ -338,7 +333,7 @@ func (txnh *TxnHeader) loadStrings(r io.ReaderAt) error {
// we rely on Load leaving len(workMem) = sum of all strings length ...
// we rely on Load leaving len(workMem) = sum of all strings length ...
_
,
err
:=
r
.
ReadAt
(
txnh
.
workMem
,
txnh
.
Pos
+
TxnHeaderFixSize
)
_
,
err
:=
r
.
ReadAt
(
txnh
.
workMem
,
txnh
.
Pos
+
TxnHeaderFixSize
)
if
err
!=
nil
{
if
err
!=
nil
{
return
txnh
.
err
(
"read strings"
,
noEOF
(
err
))
return
txnh
.
err
(
r
,
"read strings"
,
noEOF
(
err
))
}
}
// ... and presetting x to point to appropriate places in .workMem .
// ... and presetting x to point to appropriate places in .workMem .
...
@@ -360,7 +355,7 @@ func (txnh *TxnHeader) LoadPrev(r io.ReaderAt, flags TxnLoadFlags) error {
...
@@ -360,7 +355,7 @@ func (txnh *TxnHeader) LoadPrev(r io.ReaderAt, flags TxnLoadFlags) error {
lenPrev
:=
txnh
.
LenPrev
lenPrev
:=
txnh
.
LenPrev
switch
lenPrev
{
switch
lenPrev
{
case
0
:
case
0
:
bug
(
txnh
,
"LoadPrev() when .LenPrev == error"
)
bug
(
r
,
txnh
,
"LoadPrev() when .LenPrev == error"
)
case
-
1
:
case
-
1
:
return
io
.
EOF
return
io
.
EOF
...
@@ -387,18 +382,18 @@ func (txnh *TxnHeader) LoadPrev(r io.ReaderAt, flags TxnLoadFlags) error {
...
@@ -387,18 +382,18 @@ func (txnh *TxnHeader) LoadPrev(r io.ReaderAt, flags TxnLoadFlags) error {
if
err
!=
nil
{
if
err
!=
nil
{
// EOF forward is unexpected here
// EOF forward is unexpected here
if
err
==
io
.
EOF
{
if
err
==
io
.
EOF
{
err
=
txnh
.
err
(
"read"
,
io
.
ErrUnexpectedEOF
)
err
=
txnh
.
err
(
r
,
"read"
,
io
.
ErrUnexpectedEOF
)
}
}
return
err
return
err
}
}
if
txnh
.
Len
!=
lenPrev
{
if
txnh
.
Len
!=
lenPrev
{
return
checkErr
(
txnh
,
"head/tail lengths mismatch: %v, %v"
,
txnh
.
Len
,
lenPrev
)
return
checkErr
(
r
,
txnh
,
"head/tail lengths mismatch: %v, %v"
,
txnh
.
Len
,
lenPrev
)
}
}
// check tid↓ if we had txnh for "cur" loaded
// check tid↓ if we had txnh for "cur" loaded
if
lenCur
>
0
&&
txnh
.
Tid
>=
tidCur
{
if
lenCur
>
0
&&
txnh
.
Tid
>=
tidCur
{
return
checkErr
(
txnh
,
"tid monitonity broken: %v ; next: %v"
,
txnh
.
Tid
,
tidCur
)
return
checkErr
(
r
,
txnh
,
"tid monitonity broken: %v ; next: %v"
,
txnh
.
Tid
,
tidCur
)
}
}
return
nil
return
nil
...
@@ -412,7 +407,7 @@ func (txnh *TxnHeader) LoadNext(r io.ReaderAt, flags TxnLoadFlags) error {
...
@@ -412,7 +407,7 @@ func (txnh *TxnHeader) LoadNext(r io.ReaderAt, flags TxnLoadFlags) error {
posCur
:=
txnh
.
Pos
posCur
:=
txnh
.
Pos
switch
lenCur
{
switch
lenCur
{
case
0
:
case
0
:
bug
(
txnh
,
"LoadNext() when .Len == error"
)
bug
(
r
,
txnh
,
"LoadNext() when .Len == error"
)
case
-
1
:
case
-
1
:
return
io
.
EOF
return
io
.
EOF
...
@@ -430,7 +425,7 @@ func (txnh *TxnHeader) LoadNext(r io.ReaderAt, flags TxnLoadFlags) error {
...
@@ -430,7 +425,7 @@ func (txnh *TxnHeader) LoadNext(r io.ReaderAt, flags TxnLoadFlags) error {
// NOTE also: err could be EOF
// NOTE also: err could be EOF
if
txnh
.
LenPrev
!=
0
&&
txnh
.
LenPrev
!=
lenCur
{
if
txnh
.
LenPrev
!=
0
&&
txnh
.
LenPrev
!=
lenCur
{
t
:=
&
TxnHeader
{
Pos
:
posCur
}
// txn for which we discovered problem
t
:=
&
TxnHeader
{
Pos
:
posCur
}
// txn for which we discovered problem
return
checkErr
(
t
,
"head/tail lengths mismatch: %v, %v"
,
lenCur
,
txnh
.
LenPrev
)
return
checkErr
(
r
,
t
,
"head/tail lengths mismatch: %v, %v"
,
lenCur
,
txnh
.
LenPrev
)
}
}
if
err
!=
nil
{
if
err
!=
nil
{
...
@@ -439,7 +434,7 @@ func (txnh *TxnHeader) LoadNext(r io.ReaderAt, flags TxnLoadFlags) error {
...
@@ -439,7 +434,7 @@ func (txnh *TxnHeader) LoadNext(r io.ReaderAt, flags TxnLoadFlags) error {
// check tid↑
// check tid↑
if
txnh
.
Tid
<=
tidCur
{
if
txnh
.
Tid
<=
tidCur
{
return
checkErr
(
txnh
,
"tid↑ broken: %v ; prev: %v"
,
txnh
.
Tid
,
tidCur
)
return
checkErr
(
r
,
txnh
,
"tid↑ broken: %v ; prev: %v"
,
txnh
.
Tid
,
tidCur
)
}
}
return
nil
return
nil
...
@@ -468,48 +463,48 @@ func (dh *DataHeader) Load(r io.ReaderAt, pos int64) error {
...
@@ -468,48 +463,48 @@ func (dh *DataHeader) Load(r io.ReaderAt, pos int64) error {
dh
.
Pos
=
-
1
// ~ error
dh
.
Pos
=
-
1
// ~ error
if
pos
<
dataValidFrom
{
if
pos
<
dataValidFrom
{
bug
(
dh
,
"Load() on invalid position"
)
bug
(
r
,
dh
,
"Load() on invalid position"
)
}
}
_
,
err
:=
r
.
ReadAt
(
dh
.
workMem
[
:
],
pos
)
_
,
err
:=
r
.
ReadAt
(
dh
.
workMem
[
:
],
pos
)
if
err
!=
nil
{
if
err
!=
nil
{
return
dh
.
err
(
"read"
,
noEOF
(
err
))
return
dh
.
err
(
r
,
"read"
,
noEOF
(
err
))
}
}
// XXX also check oid.Valid() ?
// XXX also check oid.Valid() ?
dh
.
Oid
=
zodb
.
Oid
(
binary
.
BigEndian
.
Uint64
(
dh
.
workMem
[
0
:
]))
// XXX -> zodb.Oid.Decode() ?
dh
.
Oid
=
zodb
.
Oid
(
binary
.
BigEndian
.
Uint64
(
dh
.
workMem
[
0
:
]))
// XXX -> zodb.Oid.Decode() ?
dh
.
Tid
=
zodb
.
Tid
(
binary
.
BigEndian
.
Uint64
(
dh
.
workMem
[
8
:
]))
// XXX -> zodb.Tid.Decode() ?
dh
.
Tid
=
zodb
.
Tid
(
binary
.
BigEndian
.
Uint64
(
dh
.
workMem
[
8
:
]))
// XXX -> zodb.Tid.Decode() ?
if
!
dh
.
Tid
.
Valid
()
{
if
!
dh
.
Tid
.
Valid
()
{
return
checkErr
(
dh
,
"invalid tid: %v"
,
dh
.
Tid
)
return
checkErr
(
r
,
dh
,
"invalid tid: %v"
,
dh
.
Tid
)
}
}
dh
.
PrevRevPos
=
int64
(
binary
.
BigEndian
.
Uint64
(
dh
.
workMem
[
16
:
]))
dh
.
PrevRevPos
=
int64
(
binary
.
BigEndian
.
Uint64
(
dh
.
workMem
[
16
:
]))
dh
.
TxnPos
=
int64
(
binary
.
BigEndian
.
Uint64
(
dh
.
workMem
[
24
:
]))
dh
.
TxnPos
=
int64
(
binary
.
BigEndian
.
Uint64
(
dh
.
workMem
[
24
:
]))
if
dh
.
TxnPos
<
txnValidFrom
{
if
dh
.
TxnPos
<
txnValidFrom
{
return
checkErr
(
dh
,
"invalid txn position: %v"
,
dh
.
TxnPos
)
return
checkErr
(
r
,
dh
,
"invalid txn position: %v"
,
dh
.
TxnPos
)
}
}
if
dh
.
TxnPos
+
TxnHeaderFixSize
>
pos
{
if
dh
.
TxnPos
+
TxnHeaderFixSize
>
pos
{
return
checkErr
(
dh
,
"txn position not decreasing: %v"
,
dh
.
TxnPos
)
return
checkErr
(
r
,
dh
,
"txn position not decreasing: %v"
,
dh
.
TxnPos
)
}
}
if
dh
.
PrevRevPos
!=
0
{
// zero means there is no previous revision
if
dh
.
PrevRevPos
!=
0
{
// zero means there is no previous revision
if
dh
.
PrevRevPos
<
dataValidFrom
{
if
dh
.
PrevRevPos
<
dataValidFrom
{
return
checkErr
(
dh
,
"invalid prev revision position: %v"
,
dh
.
PrevRevPos
)
return
checkErr
(
r
,
dh
,
"invalid prev revision position: %v"
,
dh
.
PrevRevPos
)
}
}
if
dh
.
PrevRevPos
+
DataHeaderSize
>
dh
.
TxnPos
-
8
{
if
dh
.
PrevRevPos
+
DataHeaderSize
>
dh
.
TxnPos
-
8
{
return
checkErr
(
dh
,
"prev revision position (%v) overlaps with txn (%v)"
,
dh
.
PrevRevPos
,
dh
.
TxnPos
)
return
checkErr
(
r
,
dh
,
"prev revision position (%v) overlaps with txn (%v)"
,
dh
.
PrevRevPos
,
dh
.
TxnPos
)
}
}
}
}
verlen
:=
binary
.
BigEndian
.
Uint16
(
dh
.
workMem
[
32
:
])
verlen
:=
binary
.
BigEndian
.
Uint16
(
dh
.
workMem
[
32
:
])
if
verlen
!=
0
{
if
verlen
!=
0
{
return
checkErr
(
dh
,
"non-zero version: #%v"
,
verlen
)
return
checkErr
(
r
,
dh
,
"non-zero version: #%v"
,
verlen
)
}
}
dh
.
DataLen
=
int64
(
binary
.
BigEndian
.
Uint64
(
dh
.
workMem
[
34
:
]))
dh
.
DataLen
=
int64
(
binary
.
BigEndian
.
Uint64
(
dh
.
workMem
[
34
:
]))
if
dh
.
DataLen
<
0
{
if
dh
.
DataLen
<
0
{
// XXX also check DataLen < max ?
// XXX also check DataLen < max ?
return
checkErr
(
dh
,
"invalid data len: %v"
,
dh
.
DataLen
)
return
checkErr
(
r
,
dh
,
"invalid data len: %v"
,
dh
.
DataLen
)
}
}
dh
.
Pos
=
pos
dh
.
Pos
=
pos
...
@@ -531,7 +526,8 @@ func (dh *DataHeader) LoadPrevRev(r io.ReaderAt) error {
...
@@ -531,7 +526,8 @@ func (dh *DataHeader) LoadPrevRev(r io.ReaderAt) error {
err
:=
dh
.
loadPrevRev
(
r
,
dh
.
PrevRevPos
)
err
:=
dh
.
loadPrevRev
(
r
,
dh
.
PrevRevPos
)
if
err
!=
nil
{
if
err
!=
nil
{
// data record @...: -> (prev rev): data record @...: ...
// data record @...: -> (prev rev): data record @...: ...
err
=
&
DataError
{
posCur
,
"-> (prev rev)"
,
err
}
// XXX dup wrt DataHeader.err
err
=
&
RecordError
{
xio
.
Name
(
r
),
"data record"
,
posCur
,
"-> (prev rev)"
,
err
}
}
}
return
err
return
err
}
}
...
@@ -547,11 +543,11 @@ func (dh *DataHeader) loadPrevRev(r io.ReaderAt, prevPos int64) error {
...
@@ -547,11 +543,11 @@ func (dh *DataHeader) loadPrevRev(r io.ReaderAt, prevPos int64) error {
}
}
if
dh
.
Oid
!=
oid
{
if
dh
.
Oid
!=
oid
{
return
checkErr
(
dh
,
"oid mismatch: %s -> %s"
,
oid
,
dh
.
Oid
)
return
checkErr
(
r
,
dh
,
"oid mismatch: %s -> %s"
,
oid
,
dh
.
Oid
)
}
}
if
dh
.
Tid
>=
tid
{
if
dh
.
Tid
>=
tid
{
return
checkErr
(
dh
,
"tid not ↓: %s -> %s"
,
tid
,
dh
.
Tid
)
return
checkErr
(
r
,
dh
,
"tid not ↓: %s -> %s"
,
tid
,
dh
.
Tid
)
}
}
return
nil
return
nil
...
@@ -562,20 +558,20 @@ func (dh *DataHeader) loadPrevRev(r io.ReaderAt, prevPos int64) error {
...
@@ -562,20 +558,20 @@ func (dh *DataHeader) loadPrevRev(r io.ReaderAt, prevPos int64) error {
// Prerequisite: dh loaded and .LenData == 0 (data record with back-pointer).
// Prerequisite: dh loaded and .LenData == 0 (data record with back-pointer).
func
(
dh
*
DataHeader
)
LoadBackRef
(
r
io
.
ReaderAt
)
(
backPos
int64
,
err
error
)
{
func
(
dh
*
DataHeader
)
LoadBackRef
(
r
io
.
ReaderAt
)
(
backPos
int64
,
err
error
)
{
if
dh
.
DataLen
!=
0
{
if
dh
.
DataLen
!=
0
{
bug
(
dh
,
"LoadBack() on non-backpointer data header"
)
bug
(
r
,
dh
,
"LoadBack() on non-backpointer data header"
)
}
}
_
,
err
=
r
.
ReadAt
(
dh
.
workMem
[
:
8
],
dh
.
Pos
+
DataHeaderSize
)
_
,
err
=
r
.
ReadAt
(
dh
.
workMem
[
:
8
],
dh
.
Pos
+
DataHeaderSize
)
if
err
!=
nil
{
if
err
!=
nil
{
return
0
,
dh
.
err
(
"read data"
,
noEOF
(
err
))
return
0
,
dh
.
err
(
r
,
"read data"
,
noEOF
(
err
))
}
}
backPos
=
int64
(
binary
.
BigEndian
.
Uint64
(
dh
.
workMem
[
0
:
]))
backPos
=
int64
(
binary
.
BigEndian
.
Uint64
(
dh
.
workMem
[
0
:
]))
if
!
(
backPos
==
0
||
backPos
>=
dataValidFrom
)
{
if
!
(
backPos
==
0
||
backPos
>=
dataValidFrom
)
{
return
0
,
checkErr
(
dh
,
"invalid backpointer: %v"
,
backPos
)
return
0
,
checkErr
(
r
,
dh
,
"invalid backpointer: %v"
,
backPos
)
}
}
if
backPos
+
DataHeaderSize
>
dh
.
TxnPos
-
8
{
if
backPos
+
DataHeaderSize
>
dh
.
TxnPos
-
8
{
return
0
,
checkErr
(
dh
,
"backpointer (%v) overlaps with txn (%v)"
,
backPos
,
dh
.
TxnPos
)
return
0
,
checkErr
(
r
,
dh
,
"backpointer (%v) overlaps with txn (%v)"
,
backPos
,
dh
.
TxnPos
)
}
}
return
backPos
,
nil
return
backPos
,
nil
...
@@ -601,7 +597,8 @@ func (dh *DataHeader) LoadBack(r io.ReaderAt) error {
...
@@ -601,7 +597,8 @@ func (dh *DataHeader) LoadBack(r io.ReaderAt) error {
err
=
dh
.
loadPrevRev
(
r
,
backPos
)
err
=
dh
.
loadPrevRev
(
r
,
backPos
)
if
err
!=
nil
{
if
err
!=
nil
{
// data record @...: -> (prev rev): data record @...: ...
// data record @...: -> (prev rev): data record @...: ...
err
=
&
DataError
{
posCur
,
"-> (back)"
,
err
}
// XXX dup wrt DataHeader.err
err
=
&
RecordError
{
xio
.
Name
(
r
),
"data record"
,
posCur
,
"-> (back)"
,
err
}
}
}
return
err
return
err
...
@@ -615,7 +612,7 @@ func (dh *DataHeader) LoadBack(r io.ReaderAt) error {
...
@@ -615,7 +612,7 @@ func (dh *DataHeader) LoadBack(r io.ReaderAt) error {
func
(
dh
*
DataHeader
)
LoadNext
(
r
io
.
ReaderAt
,
txnh
*
TxnHeader
)
error
{
func
(
dh
*
DataHeader
)
LoadNext
(
r
io
.
ReaderAt
,
txnh
*
TxnHeader
)
error
{
err
:=
dh
.
loadNext
(
r
,
txnh
)
err
:=
dh
.
loadNext
(
r
,
txnh
)
if
err
!=
nil
&&
err
!=
io
.
EOF
{
if
err
!=
nil
&&
err
!=
io
.
EOF
{
err
=
txnh
.
err
(
"-> (iter data)"
,
err
)
err
=
txnh
.
err
(
r
,
"-> (iter data)"
,
err
)
}
}
return
err
return
err
}
}
...
@@ -632,7 +629,8 @@ func (dh *DataHeader) loadNext(r io.ReaderAt, txnh *TxnHeader) error {
...
@@ -632,7 +629,8 @@ func (dh *DataHeader) loadNext(r io.ReaderAt, txnh *TxnHeader) error {
}
}
if
nextPos
+
DataHeaderSize
>
txnTailPos
{
if
nextPos
+
DataHeaderSize
>
txnTailPos
{
return
&
DataError
{
nextPos
,
"check"
,
// XXX dup wrt DataHeader.err
return
&
RecordError
{
xio
.
Name
(
r
),
"data record"
,
nextPos
,
"check"
,
fmt
.
Errorf
(
"data record header [..., %d] overlaps txn boundary [..., %d)"
,
fmt
.
Errorf
(
"data record header [..., %d] overlaps txn boundary [..., %d)"
,
nextPos
+
DataHeaderSize
,
txnTailPos
)}
nextPos
+
DataHeaderSize
,
txnTailPos
)}
}
}
...
@@ -643,13 +641,13 @@ func (dh *DataHeader) loadNext(r io.ReaderAt, txnh *TxnHeader) error {
...
@@ -643,13 +641,13 @@ func (dh *DataHeader) loadNext(r io.ReaderAt, txnh *TxnHeader) error {
}
}
if
dh
.
Tid
!=
txnh
.
Tid
{
if
dh
.
Tid
!=
txnh
.
Tid
{
return
checkErr
(
dh
,
"tid mismatch: %s -> %s"
,
txnh
.
Tid
,
dh
.
Tid
)
return
checkErr
(
r
,
dh
,
"tid mismatch: %s -> %s"
,
txnh
.
Tid
,
dh
.
Tid
)
}
}
if
dh
.
TxnPos
!=
txnh
.
Pos
{
if
dh
.
TxnPos
!=
txnh
.
Pos
{
return
checkErr
(
dh
,
"txn position not pointing back: %d"
,
dh
.
TxnPos
)
return
checkErr
(
r
,
dh
,
"txn position not pointing back: %d"
,
dh
.
TxnPos
)
}
}
if
dh
.
Pos
+
dh
.
Len
()
>
txnTailPos
{
if
dh
.
Pos
+
dh
.
Len
()
>
txnTailPos
{
return
checkErr
(
dh
,
"data record [..., %d) overlaps txn boundary [..., %d)"
,
return
checkErr
(
r
,
dh
,
"data record [..., %d) overlaps txn boundary [..., %d)"
,
dh
.
Pos
+
dh
.
Len
(),
txnTailPos
)
dh
.
Pos
+
dh
.
Len
(),
txnTailPos
)
}
}
...
@@ -677,7 +675,7 @@ func (dh *DataHeader) LoadData(r io.ReaderAt) (*zodb.Buf, error) {
...
@@ -677,7 +675,7 @@ func (dh *DataHeader) LoadData(r io.ReaderAt) (*zodb.Buf, error) {
_
,
err
:=
r
.
ReadAt
(
buf
.
Data
,
dh
.
Pos
+
DataHeaderSize
)
_
,
err
:=
r
.
ReadAt
(
buf
.
Data
,
dh
.
Pos
+
DataHeaderSize
)
if
err
!=
nil
{
if
err
!=
nil
{
buf
.
Release
()
buf
.
Release
()
return
nil
,
dh
.
err
(
"read data"
,
noEOF
(
err
))
return
nil
,
dh
.
err
(
r
,
"read data"
,
noEOF
(
err
))
}
}
return
buf
,
nil
return
buf
,
nil
...
...
go/zodb/storage/fs1/fs1tools/dump.go
View file @
375efa1e
...
@@ -29,6 +29,7 @@ import (
...
@@ -29,6 +29,7 @@ import (
"lab.nexedi.com/kirr/neo/go/zodb"
"lab.nexedi.com/kirr/neo/go/zodb"
"lab.nexedi.com/kirr/neo/go/zodb/storage/fs1"
"lab.nexedi.com/kirr/neo/go/zodb/storage/fs1"
"lab.nexedi.com/kirr/neo/go/xcommon/xio"
"lab.nexedi.com/kirr/go123/prog"
"lab.nexedi.com/kirr/go123/prog"
"lab.nexedi.com/kirr/go123/xbytes"
"lab.nexedi.com/kirr/go123/xbytes"
...
@@ -362,7 +363,8 @@ func (d *DumperFsTail) DumpTxn(buf *xfmt.Buffer, it *fs1.Iter) error {
...
@@ -362,7 +363,8 @@ func (d *DumperFsTail) DumpTxn(buf *xfmt.Buffer, it *fs1.Iter) error {
if
err
==
io
.
EOF
{
if
err
==
io
.
EOF
{
err
=
io
.
ErrUnexpectedEOF
// XXX -> noEOF(err)
err
=
io
.
ErrUnexpectedEOF
// XXX -> noEOF(err)
}
}
return
&
fs1
.
TxnError
{
txnh
.
Pos
,
"read data payload"
,
err
}
// XXX dup wrt fs1.TxnHeader.err
return
&
fs1
.
RecordError
{
xio
.
Name
(
it
.
R
),
"transaction record"
,
txnh
.
Pos
,
"read data payload"
,
err
}
}
}
// print information about read txn record
// print information about read txn record
...
...
go/zodb/storage/fs1/py/gen-testdata
View file @
375efa1e
...
@@ -62,12 +62,13 @@ def main():
...
@@ -62,12 +62,13 @@ def main():
txnLenPrev
=
-
1
txnLenPrev
=
-
1
for
txn
in
stor
.
iterator
():
# txn is TransactionRecord
for
txn
in
stor
.
iterator
():
# txn is TransactionRecord
# txn.extension is already depickled dict - we want to put raw data from file
# txn.extension is already depickled dict - we want to put raw data from file
# also we need to access txn record legth which is not provided by higher-level iterator
# also we need to access txn record le
n
gth which is not provided by higher-level iterator
# do deep-dive into FileStorage
# do deep-dive into FileStorage
th
=
stor
.
_read_txn_header
(
txn
.
_tpos
)
th
=
stor
.
_read_txn_header
(
txn
.
_tpos
)
assert
th
.
tid
==
txn
.
tid
assert
th
.
tid
==
txn
.
tid
assert
th
.
tlen
==
txn
.
_tend
-
txn
.
_tpos
assert
th
.
tlen
==
txn
.
_tend
-
txn
.
_tpos
# fs1/go keeps in RAM whole txn length, not len-8 as it is on disk
txnLen
=
th
.
tlen
+
8
txnLen
=
th
.
tlen
+
8
emit
(
"
\
t
{"
)
emit
(
"
\
t
{"
)
...
...
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