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
0
Issues
0
List
Boards
Labels
Milestones
Merge Requests
0
Merge Requests
0
CI / CD
CI / CD
Pipelines
Jobs
Schedules
Analytics
Analytics
CI / CD
Repository
Value Stream
Wiki
Wiki
Snippets
Snippets
Members
Members
Collapse sidebar
Close sidebar
Activity
Graph
Create a new issue
Jobs
Commits
Issue Boards
Open sidebar
Levin Zimmermann
neoppod
Commits
5404250a
Commit
5404250a
authored
Feb 14, 2017
by
Kirill Smelkov
Browse files
Options
Browse Files
Download
Email Patches
Plain Diff
.
parent
dacbb6cf
Changes
1
Show whitespace changes
Inline
Side-by-side
Showing
1 changed file
with
190 additions
and
109 deletions
+190
-109
t/neo/storage/fs1/index.go
t/neo/storage/fs1/index.go
+190
-109
No files found.
t/neo/storage/fs1/index.go
View file @
5404250a
...
@@ -16,9 +16,14 @@
...
@@ -16,9 +16,14 @@
package
fs1
package
fs1
import
(
import
(
"bufio"
"bytes"
"bytes"
"encoding/binary"
"encoding/binary"
"fmt"
"io"
"io"
"net"
"os"
"strconv"
"../../zodb"
"../../zodb"
"./fsb"
"./fsb"
...
@@ -73,6 +78,8 @@ func (fsi *fsIndex) Save(topPos int64, w io.Writer) error {
...
@@ -73,6 +78,8 @@ func (fsi *fsIndex) Save(topPos int64, w io.Writer) error {
p
:=
pickle
.
NewEncoder
(
w
)
p
:=
pickle
.
NewEncoder
(
w
)
err
:=
p
.
Encode
(
topPos
)
err
:=
p
.
Encode
(
topPos
)
{
if
err
!=
nil
{
if
err
!=
nil
{
goto
out
goto
out
}
}
...
@@ -84,7 +91,6 @@ func (fsi *fsIndex) Save(topPos int64, w io.Writer) error {
...
@@ -84,7 +91,6 @@ func (fsi *fsIndex) Save(topPos int64, w io.Writer) error {
posBuf
:=
[]
byte
{}
// current pos[0:6]pos[0:6]...
posBuf
:=
[]
byte
{}
// current pos[0:6]pos[0:6]...
var
t
[
2
]
interface
{}
// tuple for (oid, fsBucket.toString())
var
t
[
2
]
interface
{}
// tuple for (oid, fsBucket.toString())
e
,
err
:=
fsi
.
SeekFirst
()
e
,
err
:=
fsi
.
SeekFirst
()
if
err
==
io
.
EOF
{
// always only io.EOF indicating an empty btree
if
err
==
io
.
EOF
{
// always only io.EOF indicating an empty btree
goto
skip
goto
skip
...
@@ -123,15 +129,16 @@ func (fsi *fsIndex) Save(topPos int64, w io.Writer) error {
...
@@ -123,15 +129,16 @@ func (fsi *fsIndex) Save(topPos int64, w io.Writer) error {
e
.
Close
()
e
.
Close
()
skip
:
skip
:
err
=
p
.
Encode
(
pickle
.
None
{})
err
=
p
.
Encode
(
pickle
.
None
{})
}
out
:
out
:
if
err
==
nil
{
if
err
==
nil
{
return
err
return
err
}
}
if
_
,
ok
:=
err
.
(
pi
kle
.
TypeError
);
ok
{
if
_
,
ok
:=
err
.
(
*
pic
kle
.
TypeError
);
ok
{
panic
(
err
)
// all our types are expected to be supported by pickle
panic
(
err
)
// all our types are expected to be supported by pickle
}
}
...
@@ -140,26 +147,42 @@ out:
...
@@ -140,26 +147,42 @@ out:
return
&
IndexIOError
{
"save"
,
err
}
return
&
IndexIOError
{
"save"
,
err
}
}
}
// IndexLoadError is the errortype returned by index load routines
type
IndexLoadError
struct
{
Filename
string
Pos
int64
Err
error
}
func
(
e
*
IndexLoadError
)
Error
()
string
{
s
:=
e
.
Filename
if
s
!=
""
{
s
+=
": "
}
s
+=
"pickle @"
+
strconv
.
FormatInt
(
e
.
Pos
,
10
)
+
": "
s
+=
e
.
Err
.
Error
()
return
s
}
// LoadIndex loads index from a reader
// LoadIndex loads index from a reader
func
LoadIndex
(
r
io
.
Reader
)
(
topPos
int64
,
fsi
*
fsIndex
,
err
error
)
{
func
LoadIndex
(
r
io
.
Reader
)
(
topPos
int64
,
fsi
*
fsIndex
,
err
error
)
{
p
:=
pickle
.
NewDecoder
(
r
)
xr
:=
NewBufReader
(
r
)
// by passing bufio.Reader directly we make sure it won't create one internally
// if we can know file position we can show it in error context
p
:=
pickle
.
NewDecoder
(
xr
.
Reader
)
rseek
,
_
:=
r
.
(
io
.
Seeker
)
var
picklePos
int64
var
rpos
int64
decode
:=
func
()
(
interface
{},
error
)
{
if
rseek
!=
nil
{
rpos
=
rseek
.
Seek
(
...
)
// XXX not ok as p buffers r internally
}
}
{
picklePos
=
xr
.
InputOffset
()
xtopPos
,
err
:=
p
.
Decode
()
xtopPos
,
err
:=
p
.
Decode
()
if
err
!=
nil
{
if
err
!=
nil
{
// TODO err
goto
out
}
}
topPos
,
ok
:=
xtopPos
.
(
int64
)
var
ok
bool
topPos
,
ok
=
xtopPos
.
(
int64
)
if
!
ok
{
if
!
ok
{
// TODO err
err
=
fmt
.
Errorf
(
"topPos is %T (expected int64)"
,
xtopPos
)
goto
out
}
}
fsi
=
&
fsIndex
{}
// TODO cmpFunc ...
fsi
=
&
fsIndex
{}
// TODO cmpFunc ...
...
@@ -168,14 +191,17 @@ func LoadIndex(r io.Reader) (topPos int64, fsi *fsIndex, err error) {
...
@@ -168,14 +191,17 @@ func LoadIndex(r io.Reader) (topPos int64, fsi *fsIndex, err error) {
loop
:
loop
:
for
{
for
{
// load/decode next entry
picklePos
=
xr
.
InputOffset
()
xv
,
err
:=
p
.
Decode
()
xv
,
err
:=
p
.
Decode
()
if
err
!=
nil
{
if
err
!=
nil
{
// TODO err
goto
out
}
}
switch
xv
.
(
type
)
{
switch
xv
.
(
type
)
{
default
:
default
:
// TODO err
err
=
fmt
.
Errorf
(
"invalid entry: type %T"
,
xv
)
break
goto
out
case
pickle
.
None
:
case
pickle
.
None
:
break
loop
break
loop
...
@@ -184,25 +210,40 @@ loop:
...
@@ -184,25 +210,40 @@ loop:
// so far ok
// so far ok
}
}
// unpack entry tuple -> oidPrefix, fsBucket
v
:=
xv
.
([]
interface
{})
v
:=
xv
.
([]
interface
{})
if
len
(
v
)
!=
2
{
if
len
(
v
)
!=
2
{
// TODO err
err
=
fmt
.
Errorf
(
"invalid entry: len = %i"
,
len
(
v
))
goto
out
}
}
// decode oidPrefix
xoidPrefixStr
:=
v
[
0
]
xoidPrefixStr
:=
v
[
0
]
oidPrefixStr
,
ok
:=
xoidPrefixStr
.
(
string
)
oidPrefixStr
,
ok
:=
xoidPrefixStr
.
(
string
)
if
!
ok
||
len
(
oidPrefixStr
)
!=
6
{
if
!
ok
{
// TODO
err
=
fmt
.
Errorf
(
"invalid oidPrefix: type %T"
,
xoidPrefixStr
)
goto
out
}
if
l
:=
len
(
oidPrefixStr
);
l
!=
6
{
err
=
fmt
.
Errorf
(
"invalid oidPrefix: len = %i"
,
l
)
goto
out
}
}
copy
(
oidb
[
:
],
oidPrefixStr
)
copy
(
oidb
[
:
],
oidPrefixStr
)
oidPrefix
:=
zodb
.
Oid
(
binary
.
BigEndian
.
Uint64
(
oidb
[
:
]))
oidPrefix
:=
zodb
.
Oid
(
binary
.
BigEndian
.
Uint64
(
oidb
[
:
]))
// check fsBucket
xkvStr
:=
v
[
1
]
xkvStr
:=
v
[
1
]
kvStr
,
ok
:=
xkvStr
.
(
string
)
kvStr
,
ok
:=
xkvStr
.
(
string
)
if
!
ok
||
len
(
kvStr
)
%
8
!=
0
{
if
!
ok
{
// TODO
err
=
fmt
.
Errorf
(
"invalid fsBucket: type %T"
,
xkvStr
)
goto
out
}
if
l
:=
len
(
kvStr
);
l
%
8
!=
0
{
err
=
fmt
.
Errorf
(
"invalid fsBucket: len = %i"
,
l
)
goto
out
}
}
// load btree from fsBucket entries
kvBuf
:=
mem
.
Bytes
(
kvStr
)
kvBuf
:=
mem
.
Bytes
(
kvStr
)
n
:=
len
(
kvBuf
)
/
8
n
:=
len
(
kvBuf
)
/
8
...
@@ -213,26 +254,66 @@ loop:
...
@@ -213,26 +254,66 @@ loop:
oid
:=
zodb
.
Oid
(
binary
.
BigEndian
.
Uint16
(
oidBuf
[
i
*
2
:
]))
oid
:=
zodb
.
Oid
(
binary
.
BigEndian
.
Uint16
(
oidBuf
[
i
*
2
:
]))
oid
|=
oidPrefix
oid
|=
oidPrefix
copy
(
posb
[
2
:
],
posBuf
[
i
*
6
:
])
copy
(
posb
[
2
:
],
posBuf
[
i
*
6
:
])
tid
:=
zodb
.
Tid
(
binary
.
BigEndian
.
Uint64
(
posb
[
:
]))
pos
:=
int64
(
binary
.
BigEndian
.
Uint64
(
posb
[
:
]))
fsi
.
Set
(
oid
,
tid
)
fsi
.
Set
(
oid
,
pos
)
}
}
}
}
}
return
topPos
,
fsi
,
nil
out
:
out
:
if
err
==
nil
{
if
err
==
nil
{
return
topPos
,
fsi
,
err
return
topPos
,
fsi
,
err
}
}
rname
:=
IOName
(
r
)
return
0
,
nil
,
&
IndexLoadError
{
IOName
(
r
),
picklePos
,
err
}
}
// CountReader is an io.Reader that count total bytes read.
type
CountReader
struct
{
io
.
Reader
nread
int64
}
// same for file name
func
(
r
*
CountReader
)
Read
(
p
[]
byte
)
(
int
,
error
)
{
rname
,
_
:=
r
.
(
interface
{
Name
()
string
})
n
,
err
:=
r
.
Reader
.
Read
(
p
)
r
.
nread
+=
int64
(
n
)
return
n
,
err
}
// InputOffset returns current position in input stream
func
(
r
*
CountReader
)
InputOffset
()
int64
{
return
r
.
nread
}
}
// BufReader is a bufio.Reader + bell & whistles
type
BufReader
struct
{
*
bufio
.
Reader
cr
*
CountReader
}
func
NewBufReader
(
r
io
.
Reader
)
*
BufReader
{
// idempotent(BufReader)
if
r
,
ok
:=
r
.
(
*
BufReader
);
ok
{
return
r
}
// idempotent(CountReader)
cr
,
ok
:=
r
.
(
*
CountReader
)
if
!
ok
{
cr
=
&
CountReader
{
r
,
0
}
}
return
&
BufReader
{
bufio
.
NewReader
(
cr
),
cr
}
}
// InputOffset returns current position in input stream
func
(
r
*
BufReader
)
InputOffset
()
int64
{
return
r
.
cr
.
InputOffset
()
-
int64
(
r
.
Reader
.
Buffered
())
}
// IOName returns a "filename" associated with io.Reader, io.Writer, net.Conn, ...
// IOName returns a "filename" associated with io.Reader, io.Writer, net.Conn, ...
// if name cannot be deterined - "" is returned.
// if name cannot be deterined - "" is returned.
...
@@ -245,14 +326,14 @@ func IOName(f interface {}) string {
...
@@ -245,14 +326,14 @@ func IOName(f interface {}) string {
case
net
.
Conn
:
case
net
.
Conn
:
// XXX not including LocalAddr is ok?
// XXX not including LocalAddr is ok?
return
f
.
RemoteAddr
.
String
()
return
f
.
RemoteAddr
()
.
String
()
case
*
io
.
LimitedReader
:
case
*
io
.
LimitedReader
:
return
IOName
(
f
.
R
)
return
IOName
(
f
.
R
)
case
*
io
.
PipeReader
:
case
*
io
.
PipeReader
:
fallthrough
return
"pipe"
case
*
io
.
PipeWriter
:
case
*
io
.
PipeWriter
:
return
"pipe"
return
"pipe"
...
...
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