Skip to content
GitLab
Projects
Groups
Snippets
Help
Loading...
Help
What's new
10
Help
Support
Community forum
Keyboard shortcuts
?
Submit feedback
Contribute to GitLab
Sign in
Toggle navigation
Open sidebar
dms3
go-merkledag
Commits
1268b9cc
Commit
1268b9cc
authored
Sep 01, 2016
by
Jeromy
Browse files
Options
Browse Files
Download
Email Patches
Plain Diff
integrate CIDv0
License: MIT Signed-off-by:
Jeromy
<
why@ipfs.io
>
parent
113e2390
Changes
8
Show whitespace changes
Inline
Side-by-side
Showing
8 changed files
with
194 additions
and
222 deletions
+194
-222
coding.go
coding.go
+4
-3
merkledag.go
merkledag.go
+94
-101
merkledag_test.go
merkledag_test.go
+36
-48
node.go
node.go
+35
-21
node_test.go
node_test.go
+4
-4
traverse/traverse.go
traverse/traverse.go
+1
-5
utils/diff.go
utils/diff.go
+11
-20
utils/utils_test.go
utils/utils_test.go
+9
-20
No files found.
coding.go
View file @
1268b9cc
...
...
@@ -4,10 +4,11 @@ import (
"fmt"
"sort"
mh
"gx/ipfs/QmYf7ng2hG5XBtJA3tN34DQ2GUN5HNksEw1rLDkmr6vGku/go-multihash"
pb
"github.com/ipfs/go-ipfs/merkledag/pb"
mh
"gx/ipfs/QmYf7ng2hG5XBtJA3tN34DQ2GUN5HNksEw1rLDkmr6vGku/go-multihash"
u
"gx/ipfs/QmZNVWh8LLjAavuQ2JXuFmuYH3C11xo988vSgp7UQrTRj1/go-ipfs-util"
cid
"gx/ipfs/QmfSc2xehWmWLnwwYR91Y8QF4xdASypTFVknutoKQS3GHp/go-cid"
)
// for now, we use a PBNode intermediate thing.
...
...
@@ -83,7 +84,7 @@ func (n *Node) EncodeProtobuf(force bool) ([]byte, error) {
}
if
n
.
cached
==
nil
{
n
.
cached
=
u
.
Hash
(
n
.
encoded
)
n
.
cached
=
cid
.
NewCidV0
(
u
.
Hash
(
n
.
encoded
)
)
}
return
n
.
encoded
,
nil
...
...
merkledag.go
View file @
1268b9cc
...
...
@@ -6,11 +6,12 @@ import (
"strings"
"sync"
blocks
"github.com/ipfs/go-ipfs/blocks"
key
"github.com/ipfs/go-ipfs/blocks/key"
bserv
"github.com/ipfs/go-ipfs/blockservice"
logging
"gx/ipfs/QmSpJByNKFX1sCsHBEp3R73FL4NF6FnQTEGyNAXHm2GS52/go-log"
"gx/ipfs/QmZy2y8t9zQH2a1b8q2ZSLKp17ATuJoCNxxyMFG5qFExpt/go-net/context"
cid
"gx/ipfs/QmfSc2xehWmWLnwwYR91Y8QF4xdASypTFVknutoKQS3GHp/go-cid"
)
var
log
=
logging
.
Logger
(
"merkledag"
)
...
...
@@ -18,13 +19,13 @@ var ErrNotFound = fmt.Errorf("merkledag: not found")
// DAGService is an IPFS Merkle DAG service.
type
DAGService
interface
{
Add
(
*
Node
)
(
key
.
Key
,
error
)
Get
(
context
.
Context
,
key
.
Key
)
(
*
Node
,
error
)
Add
(
*
Node
)
(
*
cid
.
Cid
,
error
)
Get
(
context
.
Context
,
*
cid
.
Cid
)
(
*
Node
,
error
)
Remove
(
*
Node
)
error
// GetDAG returns, in order, all the single leve child
// nodes of the passed in node.
GetMany
(
context
.
Context
,
[]
key
.
Key
)
<-
chan
*
NodeOption
GetMany
(
context
.
Context
,
[]
*
cid
.
Cid
)
<-
chan
*
NodeOption
Batch
()
*
Batch
}
...
...
@@ -43,24 +44,12 @@ type dagService struct {
}
// Add adds a node to the dagService, storing the block in the BlockService
func
(
n
*
dagService
)
Add
(
nd
*
Node
)
(
key
.
Key
,
error
)
{
func
(
n
*
dagService
)
Add
(
nd
*
Node
)
(
*
cid
.
Cid
,
error
)
{
if
n
==
nil
{
// FIXME remove this assertion. protect with constructor invariant
return
""
,
fmt
.
Errorf
(
"dagService is nil"
)
}
d
,
err
:=
nd
.
EncodeProtobuf
(
false
)
if
err
!=
nil
{
return
""
,
err
}
mh
,
err
:=
nd
.
Multihash
()
if
err
!=
nil
{
return
""
,
err
return
nil
,
fmt
.
Errorf
(
"dagService is nil"
)
}
b
,
_
:=
blocks
.
NewBlockWithHash
(
d
,
mh
)
return
n
.
Blocks
.
AddBlock
(
b
)
return
n
.
Blocks
.
AddObject
(
nd
)
}
func
(
n
*
dagService
)
Batch
()
*
Batch
{
...
...
@@ -68,56 +57,57 @@ func (n *dagService) Batch() *Batch {
}
// Get retrieves a node from the dagService, fetching the block in the BlockService
func
(
n
*
dagService
)
Get
(
ctx
context
.
Context
,
k
key
.
Key
)
(
*
Node
,
error
)
{
if
k
==
""
{
return
nil
,
ErrNotFound
}
func
(
n
*
dagService
)
Get
(
ctx
context
.
Context
,
c
*
cid
.
Cid
)
(
*
Node
,
error
)
{
if
n
==
nil
{
return
nil
,
fmt
.
Errorf
(
"dagService is nil"
)
}
ctx
,
cancel
:=
context
.
WithCancel
(
ctx
)
defer
cancel
()
b
,
err
:=
n
.
Blocks
.
GetBlock
(
ctx
,
k
)
b
,
err
:=
n
.
Blocks
.
GetBlock
(
ctx
,
c
)
if
err
!=
nil
{
if
err
==
bserv
.
ErrNotFound
{
return
nil
,
ErrNotFound
}
return
nil
,
fmt
.
Errorf
(
"Failed to get block for %s: %v"
,
k
.
B58String
()
,
err
)
return
nil
,
fmt
.
Errorf
(
"Failed to get block for %s: %v"
,
c
,
err
)
}
res
,
err
:=
DecodeProtobuf
(
b
.
Data
())
var
res
*
Node
switch
c
.
Type
()
{
case
cid
.
Protobuf
:
out
,
err
:=
DecodeProtobuf
(
b
.
RawData
())
if
err
!=
nil
{
if
strings
.
Contains
(
err
.
Error
(),
"Unmarshal failed"
)
{
return
nil
,
fmt
.
Errorf
(
"The block referred to by '%s' was not a valid merkledag node"
,
k
)
return
nil
,
fmt
.
Errorf
(
"The block referred to by '%s' was not a valid merkledag node"
,
c
)
}
return
nil
,
fmt
.
Errorf
(
"Failed to decode Protocol Buffers: %v"
,
err
)
}
res
=
out
default
:
return
nil
,
fmt
.
Errorf
(
"unrecognized formatting type"
)
}
res
.
cached
=
k
.
ToMultihash
()
res
.
cached
=
c
return
res
,
nil
}
func
(
n
*
dagService
)
Remove
(
nd
*
Node
)
error
{
k
,
err
:=
nd
.
Key
()
if
err
!=
nil
{
return
err
}
return
n
.
Blocks
.
DeleteBlock
(
k
)
return
n
.
Blocks
.
DeleteObject
(
nd
)
}
// FetchGraph fetches all nodes that are children of the given node
func
FetchGraph
(
ctx
context
.
Context
,
root
*
Node
,
serv
DAGService
)
error
{
return
EnumerateChildrenAsync
(
ctx
,
serv
,
root
,
key
.
New
Key
Set
())
return
EnumerateChildrenAsync
(
ctx
,
serv
,
root
,
cid
.
NewSet
()
.
Visit
)
}
// FindLinks searches this nodes links for the given key,
// returns the indexes of any links pointing to it
func
FindLinks
(
links
[]
key
.
Key
,
k
key
.
Key
,
start
int
)
[]
int
{
func
FindLinks
(
links
[]
*
cid
.
Cid
,
c
*
cid
.
Cid
,
start
int
)
[]
int
{
var
out
[]
int
for
i
,
lnk_
k
:=
range
links
[
start
:
]
{
if
k
==
lnk_
k
{
for
i
,
lnk_
c
:=
range
links
[
start
:
]
{
if
c
.
Equals
(
lnk_
c
)
{
out
=
append
(
out
,
i
+
start
)
}
}
...
...
@@ -129,11 +119,21 @@ type NodeOption struct {
Err
error
}
func
(
ds
*
dagService
)
GetMany
(
ctx
context
.
Context
,
keys
[]
key
.
Key
)
<-
chan
*
NodeOption
{
func
cidsToKeyMapping
(
cids
[]
*
cid
.
Cid
)
map
[
key
.
Key
]
*
cid
.
Cid
{
mapping
:=
make
(
map
[
key
.
Key
]
*
cid
.
Cid
)
for
_
,
c
:=
range
cids
{
mapping
[
key
.
Key
(
c
.
Hash
())]
=
c
}
return
mapping
}
func
(
ds
*
dagService
)
GetMany
(
ctx
context
.
Context
,
keys
[]
*
cid
.
Cid
)
<-
chan
*
NodeOption
{
out
:=
make
(
chan
*
NodeOption
,
len
(
keys
))
blocks
:=
ds
.
Blocks
.
GetBlocks
(
ctx
,
keys
)
var
count
int
mapping
:=
cidsToKeyMapping
(
keys
)
go
func
()
{
defer
close
(
out
)
for
{
...
...
@@ -145,12 +145,23 @@ func (ds *dagService) GetMany(ctx context.Context, keys []key.Key) <-chan *NodeO
}
return
}
nd
,
err
:=
DecodeProtobuf
(
b
.
Data
())
c
:=
mapping
[
b
.
Key
()]
var
nd
*
Node
switch
c
.
Type
()
{
case
cid
.
Protobuf
:
decnd
,
err
:=
DecodeProtobuf
(
b
.
RawData
())
if
err
!=
nil
{
out
<-
&
NodeOption
{
Err
:
err
}
return
}
nd
.
cached
=
b
.
Key
()
.
ToMultihash
()
decnd
.
cached
=
cid
.
NewCidV0
(
b
.
Multihash
())
nd
=
decnd
default
:
out
<-
&
NodeOption
{
Err
:
fmt
.
Errorf
(
"unrecognized object type: %s"
,
c
.
Type
())}
return
}
// buffered, no need to select
out
<-
&
NodeOption
{
Node
:
nd
}
...
...
@@ -169,17 +180,17 @@ func (ds *dagService) GetMany(ctx context.Context, keys []key.Key) <-chan *NodeO
// It returns a channel of nodes, which the caller can receive
// all the child nodes of 'root' on, in proper order.
func
GetDAG
(
ctx
context
.
Context
,
ds
DAGService
,
root
*
Node
)
[]
NodeGetter
{
var
key
s
[]
key
.
Key
var
cid
s
[]
*
cid
.
Cid
for
_
,
lnk
:=
range
root
.
Links
{
key
s
=
append
(
keys
,
key
.
Key
(
lnk
.
Hash
))
cid
s
=
append
(
cids
,
cid
.
NewCidV0
(
lnk
.
Hash
))
}
return
GetNodes
(
ctx
,
ds
,
key
s
)
return
GetNodes
(
ctx
,
ds
,
cid
s
)
}
// GetNodes returns an array of 'NodeGetter' promises, with each corresponding
// to the key with the same index as the passed in keys
func
GetNodes
(
ctx
context
.
Context
,
ds
DAGService
,
keys
[]
key
.
Key
)
[]
NodeGetter
{
func
GetNodes
(
ctx
context
.
Context
,
ds
DAGService
,
keys
[]
*
cid
.
Cid
)
[]
NodeGetter
{
// Early out if no work to do
if
len
(
keys
)
==
0
{
...
...
@@ -216,14 +227,7 @@ func GetNodes(ctx context.Context, ds DAGService, keys []key.Key) []NodeGetter {
}
nd
:=
opt
.
Node
k
,
err
:=
nd
.
Key
()
if
err
!=
nil
{
log
.
Error
(
"Failed to get node key: "
,
err
)
continue
}
is
:=
FindLinks
(
keys
,
k
,
0
)
is
:=
FindLinks
(
keys
,
nd
.
Cid
(),
0
)
for
_
,
i
:=
range
is
{
count
++
promises
[
i
]
.
Send
(
nd
)
...
...
@@ -237,16 +241,12 @@ func GetNodes(ctx context.Context, ds DAGService, keys []key.Key) []NodeGetter {
}
// Remove duplicates from a list of keys
func
dedupeKeys
(
ks
[]
key
.
Key
)
[]
key
.
Key
{
kmap
:=
make
(
map
[
key
.
Key
]
struct
{})
var
out
[]
key
.
Key
for
_
,
k
:=
range
ks
{
if
_
,
ok
:=
kmap
[
k
];
!
ok
{
kmap
[
k
]
=
struct
{}{}
out
=
append
(
out
,
k
)
func
dedupeKeys
(
cids
[]
*
cid
.
Cid
)
[]
*
cid
.
Cid
{
set
:=
cid
.
NewSet
()
for
_
,
c
:=
range
cids
{
set
.
Add
(
c
)
}
}
return
out
return
set
.
Keys
()
}
func
newNodePromise
(
ctx
context
.
Context
)
NodeGetter
{
...
...
@@ -327,50 +327,44 @@ func (np *nodePromise) Get(ctx context.Context) (*Node, error) {
type
Batch
struct
{
ds
*
dagService
blocks
[]
blocks
.
Block
objects
[]
bserv
.
Object
size
int
MaxSize
int
}
func
(
t
*
Batch
)
Add
(
nd
*
Node
)
(
key
.
Key
,
error
)
{
func
(
t
*
Batch
)
Add
(
nd
*
Node
)
(
*
cid
.
Cid
,
error
)
{
d
,
err
:=
nd
.
EncodeProtobuf
(
false
)
if
err
!=
nil
{
return
""
,
err
}
mh
,
err
:=
nd
.
Multihash
()
if
err
!=
nil
{
return
""
,
err
return
nil
,
err
}
b
,
_
:=
blocks
.
NewBlockWithHash
(
d
,
mh
)
k
:=
key
.
Key
(
mh
)
t
.
blocks
=
append
(
t
.
blocks
,
b
)
t
.
size
+=
len
(
b
.
Data
())
t
.
objects
=
append
(
t
.
objects
,
nd
)
t
.
size
+=
len
(
d
)
if
t
.
size
>
t
.
MaxSize
{
return
k
,
t
.
Commit
()
return
nd
.
Cid
()
,
t
.
Commit
()
}
return
k
,
nil
return
nd
.
Cid
()
,
nil
}
func
(
t
*
Batch
)
Commit
()
error
{
_
,
err
:=
t
.
ds
.
Blocks
.
Add
Blocks
(
t
.
block
s
)
t
.
block
s
=
nil
_
,
err
:=
t
.
ds
.
Blocks
.
Add
Objects
(
t
.
object
s
)
t
.
object
s
=
nil
t
.
size
=
0
return
err
}
func
legacyCidFromLink
(
lnk
*
Link
)
*
cid
.
Cid
{
return
cid
.
NewCidV0
(
lnk
.
Hash
)
}
// EnumerateChildren will walk the dag below the given root node and add all
// unseen children to the passed in set.
// TODO: parallelize to avoid disk latency perf hits?
func
EnumerateChildren
(
ctx
context
.
Context
,
ds
DAGService
,
root
*
Node
,
set
key
.
KeySet
,
bestEffort
bool
)
error
{
func
EnumerateChildren
(
ctx
context
.
Context
,
ds
DAGService
,
root
*
Node
,
visit
func
(
*
cid
.
Cid
)
bool
,
bestEffort
bool
)
error
{
for
_
,
lnk
:=
range
root
.
Links
{
k
:=
key
.
Key
(
lnk
.
Hash
)
if
!
set
.
Has
(
k
)
{
set
.
Add
(
k
)
child
,
err
:=
ds
.
Get
(
ctx
,
k
)
c
:=
legacyCidFromLink
(
lnk
)
if
visit
(
c
)
{
child
,
err
:=
ds
.
Get
(
ctx
,
c
)
if
err
!=
nil
{
if
bestEffort
&&
err
==
ErrNotFound
{
continue
...
...
@@ -378,7 +372,7 @@ func EnumerateChildren(ctx context.Context, ds DAGService, root *Node, set key.K
return
err
}
}
err
=
EnumerateChildren
(
ctx
,
ds
,
child
,
se
t
,
bestEffort
)
err
=
EnumerateChildren
(
ctx
,
ds
,
child
,
visi
t
,
bestEffort
)
if
err
!=
nil
{
return
err
}
...
...
@@ -387,8 +381,8 @@ func EnumerateChildren(ctx context.Context, ds DAGService, root *Node, set key.K
return
nil
}
func
EnumerateChildrenAsync
(
ctx
context
.
Context
,
ds
DAGService
,
root
*
Node
,
set
key
.
KeySet
)
error
{
toprocess
:=
make
(
chan
[]
key
.
Key
,
8
)
func
EnumerateChildrenAsync
(
ctx
context
.
Context
,
ds
DAGService
,
root
*
Node
,
visit
func
(
*
cid
.
Cid
)
bool
)
error
{
toprocess
:=
make
(
chan
[]
*
cid
.
Cid
,
8
)
nodes
:=
make
(
chan
*
NodeOption
,
8
)
ctx
,
cancel
:=
context
.
WithCancel
(
ctx
)
...
...
@@ -416,13 +410,12 @@ func EnumerateChildrenAsync(ctx context.Context, ds DAGService, root *Node, set
// a node has been fetched
live
--
var
key
s
[]
key
.
Key
var
cid
s
[]
*
cid
.
Cid
for
_
,
lnk
:=
range
nd
.
Links
{
k
:=
key
.
Key
(
lnk
.
Hash
)
if
!
set
.
Has
(
k
)
{
set
.
Add
(
k
)
c
:=
legacyCidFromLink
(
lnk
)
if
visit
(
c
)
{
live
++
key
s
=
append
(
key
s
,
k
)
cid
s
=
append
(
cid
s
,
c
)
}
}
...
...
@@ -430,9 +423,9 @@ func EnumerateChildrenAsync(ctx context.Context, ds DAGService, root *Node, set
return
nil
}
if
len
(
key
s
)
>
0
{
if
len
(
cid
s
)
>
0
{
select
{
case
toprocess
<-
key
s
:
case
toprocess
<-
cid
s
:
case
<-
ctx
.
Done
()
:
return
ctx
.
Err
()
}
...
...
@@ -443,7 +436,7 @@ func EnumerateChildrenAsync(ctx context.Context, ds DAGService, root *Node, set
}
}
func
fetchNodes
(
ctx
context
.
Context
,
ds
DAGService
,
in
<-
chan
[]
key
.
Key
,
out
chan
<-
*
NodeOption
)
{
func
fetchNodes
(
ctx
context
.
Context
,
ds
DAGService
,
in
<-
chan
[]
*
cid
.
Cid
,
out
chan
<-
*
NodeOption
)
{
var
wg
sync
.
WaitGroup
defer
func
()
{
// wait for all 'get' calls to complete so we don't accidentally send
...
...
@@ -452,7 +445,7 @@ func fetchNodes(ctx context.Context, ds DAGService, in <-chan []key.Key, out cha
close
(
out
)
}()
get
:=
func
(
ks
[]
key
.
Key
)
{
get
:=
func
(
ks
[]
*
cid
.
Cid
)
{
defer
wg
.
Done
()
nodes
:=
ds
.
GetMany
(
ctx
,
ks
)
for
opt
:=
range
nodes
{
...
...
merkledag_test.go
View file @
1268b9cc
...
...
@@ -20,8 +20,10 @@ import (
mdpb
"github.com/ipfs/go-ipfs/merkledag/pb"
dstest
"github.com/ipfs/go-ipfs/merkledag/test"
uio
"github.com/ipfs/go-ipfs/unixfs/io"
u
"gx/ipfs/QmZNVWh8LLjAavuQ2JXuFmuYH3C11xo988vSgp7UQrTRj1/go-ipfs-util"
"gx/ipfs/QmZy2y8t9zQH2a1b8q2ZSLKp17ATuJoCNxxyMFG5qFExpt/go-net/context"
cid
"gx/ipfs/QmfSc2xehWmWLnwwYR91Y8QF4xdASypTFVknutoKQS3GHp/go-cid"
)
func
TestNode
(
t
*
testing
.
T
)
{
...
...
@@ -52,17 +54,9 @@ func TestNode(t *testing.T) {
fmt
.
Println
(
"encoded:"
,
e
)
}
h
,
err
:=
n
.
Multihash
()
if
err
!=
nil
{
t
.
Error
(
err
)
}
else
{
fmt
.
Println
(
"hash:"
,
h
)
}
k
,
err
:=
n
.
Key
()
if
err
!=
nil
{
t
.
Error
(
err
)
}
else
if
k
!=
key
.
Key
(
h
)
{
h
:=
n
.
Multihash
()
k
:=
n
.
Key
()
if
k
!=
key
.
Key
(
h
)
{
t
.
Error
(
"Key is not equivalent to multihash"
)
}
else
{
fmt
.
Println
(
"key: "
,
k
)
...
...
@@ -89,11 +83,7 @@ func SubtestNodeStat(t *testing.T, n *Node) {
return
}
k
,
err
:=
n
.
Key
()
if
err
!=
nil
{
t
.
Error
(
"n.Key() failed"
)
return
}
k
:=
n
.
Key
()
expected
:=
NodeStat
{
NumLinks
:
len
(
n
.
Links
),
...
...
@@ -169,10 +159,7 @@ func runBatchFetchTest(t *testing.T, read io.Reader) {
t
.
Log
(
"Added file to first node."
)
k
,
err
:=
root
.
Key
()
if
err
!=
nil
{
t
.
Fatal
(
err
)
}
c
:=
root
.
Cid
()
wg
:=
sync
.
WaitGroup
{}
errs
:=
make
(
chan
error
)
...
...
@@ -181,7 +168,7 @@ func runBatchFetchTest(t *testing.T, read io.Reader) {
wg
.
Add
(
1
)
go
func
(
i
int
)
{
defer
wg
.
Done
()
first
,
err
:=
dagservs
[
i
]
.
Get
(
ctx
,
k
)
first
,
err
:=
dagservs
[
i
]
.
Get
(
ctx
,
c
)
if
err
!=
nil
{
errs
<-
err
}
...
...
@@ -215,34 +202,17 @@ func runBatchFetchTest(t *testing.T, read io.Reader) {
}
func
assertCanGet
(
t
*
testing
.
T
,
ds
DAGService
,
n
*
Node
)
{
k
,
err
:=
n
.
Key
()
if
err
!=
nil
{
t
.
Fatal
(
err
)
}
if
_
,
err
:=
ds
.
Get
(
context
.
Background
(),
k
);
err
!=
nil
{
if
_
,
err
:=
ds
.
Get
(
context
.
Background
(),
n
.
Cid
());
err
!=
nil
{
t
.
Fatal
(
err
)
}
}
func
TestEmptyKey
(
t
*
testing
.
T
)
{
ds
:=
dstest
.
Mock
()
_
,
err
:=
ds
.
Get
(
context
.
Background
(),
key
.
Key
(
""
))
if
err
!=
ErrNotFound
{
t
.
Error
(
"dag service should error when key is nil"
,
err
)
}
}
func
TestCantGet
(
t
*
testing
.
T
)
{
ds
:=
dstest
.
Mock
()
a
:=
NodeWithData
([]
byte
(
"A"
))
k
,
err
:=
a
.
Key
()
if
err
!=
nil
{
t
.
Fatal
(
err
)
}
_
,
err
=
ds
.
Get
(
context
.
Background
(),
k
)
c
:=
a
.
Cid
()
_
,
err
:=
ds
.
Get
(
context
.
Background
(),
c
)
if
!
strings
.
Contains
(
err
.
Error
(),
"not found"
)
{
t
.
Fatal
(
"expected err not found, got: "
,
err
)
}
...
...
@@ -270,9 +240,8 @@ func TestFetchGraph(t *testing.T) {
bs
:=
bserv
.
New
(
bsis
[
1
]
.
Blockstore
,
offline
.
Exchange
(
bsis
[
1
]
.
Blockstore
))
offline_ds
:=
NewDAGService
(
bs
)
ks
:=
key
.
NewKeySet
()
err
=
EnumerateChildren
(
context
.
Background
(),
offline_ds
,
root
,
ks
,
false
)
err
=
EnumerateChildren
(
context
.
Background
(),
offline_ds
,
root
,
func
(
_
*
cid
.
Cid
)
bool
{
return
true
}
,
false
)
if
err
!=
nil
{
t
.
Fatal
(
err
)
}
...
...
@@ -288,8 +257,8 @@ func TestEnumerateChildren(t *testing.T) {
t
.
Fatal
(
err
)
}
k
s
:=
key
.
New
Key
Set
()
err
=
EnumerateChildren
(
context
.
Background
(),
ds
,
root
,
k
s
,
false
)
s
et
:=
cid
.
NewSet
()
err
=
EnumerateChildren
(
context
.
Background
(),
ds
,
root
,
s
et
.
Visit
,
false
)
if
err
!=
nil
{
t
.
Fatal
(
err
)
}
...
...
@@ -298,11 +267,11 @@ func TestEnumerateChildren(t *testing.T) {
traverse
=
func
(
n
*
Node
)
{
// traverse dag and check
for
_
,
lnk
:=
range
n
.
Links
{
k
:=
key
.
Key
(
lnk
.
Hash
)
if
!
k
s
.
Has
(
k
)
{
c
:=
cid
.
NewCidV0
(
lnk
.
Hash
)
if
!
s
et
.
Has
(
c
)
{
t
.
Fatal
(
"missing key in set!"
)
}
child
,
err
:=
ds
.
Get
(
context
.
Background
(),
k
)
child
,
err
:=
ds
.
Get
(
context
.
Background
(),
c
)
if
err
!=
nil
{
t
.
Fatal
(
err
)
}
...
...
@@ -379,3 +348,22 @@ func TestUnmarshalFailure(t *testing.T) {
n
:=
&
Node
{}
n
.
Marshal
()
}
func
TestBasicAddGet
(
t
*
testing
.
T
)
{
ds
:=
dstest
.
Mock
()
nd
:=
new
(
Node
)
c
,
err
:=
ds
.
Add
(
nd
)
if
err
!=
nil
{
t
.
Fatal
(
err
)
}
out
,
err
:=
ds
.
Get
(
context
.
Background
(),
c
)
if
err
!=
nil
{
t
.
Fatal
(
err
)
}
if
!
nd
.
Cid
()
.
Equals
(
out
.
Cid
())
{
t
.
Fatal
(
"output didnt match input"
)
}
}
node.go
View file @
1268b9cc
...
...
@@ -7,6 +7,7 @@ import (
key
"github.com/ipfs/go-ipfs/blocks/key"
mh
"gx/ipfs/QmYf7ng2hG5XBtJA3tN34DQ2GUN5HNksEw1rLDkmr6vGku/go-multihash"
cid
"gx/ipfs/QmfSc2xehWmWLnwwYR91Y8QF4xdASypTFVknutoKQS3GHp/go-cid"
)
var
ErrLinkNotFound
=
fmt
.
Errorf
(
"no link by that name"
)
...
...
@@ -20,7 +21,7 @@ type Node struct {
// cache encoded/marshaled value
encoded
[]
byte
cached
mh
.
Multihash
cached
*
cid
.
Cid
}
// NodeStat is a statistics object for a Node. Mostly sizes.
...
...
@@ -63,10 +64,8 @@ func MakeLink(n *Node) (*Link, error) {
return
nil
,
err
}
h
,
err
:=
n
.
Multihash
()
if
err
!=
nil
{
return
nil
,
err
}
h
:=
n
.
Multihash
()
return
&
Link
{
Size
:
s
,
Hash
:
h
,
...
...
@@ -75,7 +74,7 @@ func MakeLink(n *Node) (*Link, error) {
// GetNode returns the MDAG Node that this link points to
func
(
l
*
Link
)
GetNode
(
ctx
context
.
Context
,
serv
DAGService
)
(
*
Node
,
error
)
{
return
serv
.
Get
(
ctx
,
key
.
Key
(
l
.
Hash
))
return
serv
.
Get
(
ctx
,
legacyCidFromLink
(
l
))
}
func
NodeWithData
(
d
[]
byte
)
*
Node
{
...
...
@@ -184,6 +183,11 @@ func (n *Node) Copy() *Node {
return
nnode
}
func
(
n
*
Node
)
RawData
()
[]
byte
{
out
,
_
:=
n
.
EncodeProtobuf
(
false
)
return
out
}
func
(
n
*
Node
)
Data
()
[]
byte
{
return
n
.
data
}
...
...
@@ -231,13 +235,8 @@ func (n *Node) Stat() (*NodeStat, error) {
return
nil
,
err
}
key
,
err
:=
n
.
Key
()
if
err
!=
nil
{
return
nil
,
err
}
return
&
NodeStat
{
Hash
:
key
.
B58String
(),
Hash
:
n
.
Key
()
.
B58String
(),
NumLinks
:
len
(
n
.
Links
),
BlockSize
:
len
(
enc
),
LinksSize
:
len
(
enc
)
-
len
(
n
.
data
),
// includes framing.
...
...
@@ -246,19 +245,34 @@ func (n *Node) Stat() (*NodeStat, error) {
},
nil
}
func
(
n
*
Node
)
Key
()
key
.
Key
{
return
key
.
Key
(
n
.
Multihash
())
}
func
(
n
*
Node
)
Loggable
()
map
[
string
]
interface
{}
{
return
map
[
string
]
interface
{}{
"node"
:
n
.
String
(),
}
}
func
(
n
*
Node
)
Cid
()
*
cid
.
Cid
{
h
:=
n
.
Multihash
()
return
cid
.
NewCidV0
(
h
)
}
func
(
n
*
Node
)
String
()
string
{
return
n
.
Cid
()
.
String
()
}
// Multihash hashes the encoded data of this node.
func
(
n
*
Node
)
Multihash
()
(
mh
.
Multihash
,
error
)
{
func
(
n
*
Node
)
Multihash
()
mh
.
Multihash
{
// NOTE: EncodeProtobuf generates the hash and puts it in n.cached.
_
,
err
:=
n
.
EncodeProtobuf
(
false
)
if
err
!=
nil
{
return
nil
,
err
// Note: no possibility exists for an error to be returned through here
panic
(
err
)
}
return
n
.
cached
,
nil
}
// Key returns the Multihash as a key, for maps.
func
(
n
*
Node
)
Key
()
(
key
.
Key
,
error
)
{
h
,
err
:=
n
.
Multihash
()
return
key
.
Key
(
h
),
err
return
n
.
cached
.
Hash
()
}
node_test.go
View file @
1268b9cc
...
...
@@ -67,9 +67,9 @@ func TestFindLink(t *testing.T) {
nd
:=
&
Node
{
Links
:
[]
*
Link
{
&
Link
{
Name
:
"a"
,
Hash
:
k
.
ToMultih
ash
()},
&
Link
{
Name
:
"c"
,
Hash
:
k
.
ToMultih
ash
()},
&
Link
{
Name
:
"b"
,
Hash
:
k
.
ToMultih
ash
()},
&
Link
{
Name
:
"a"
,
Hash
:
k
.
H
ash
()},
&
Link
{
Name
:
"c"
,
Hash
:
k
.
H
ash
()},
&
Link
{
Name
:
"b"
,
Hash
:
k
.
H
ash
()},
},
}
...
...
@@ -107,7 +107,7 @@ func TestFindLink(t *testing.T) {
t
.
Fatal
(
err
)
}
if
olnk
.
Hash
.
B58String
()
==
k
.
B58
String
()
{
if
olnk
.
Hash
.
B58String
()
==
k
.
String
()
{
t
.
Fatal
(
"new link should have different hash"
)
}
}
...
...
traverse/traverse.go
View file @
1268b9cc
...
...
@@ -41,11 +41,7 @@ type traversal struct {
func
(
t
*
traversal
)
shouldSkip
(
n
*
mdag
.
Node
)
(
bool
,
error
)
{
if
t
.
opts
.
SkipDuplicates
{
k
,
err
:=
n
.
Key
()
if
err
!=
nil
{
return
true
,
err
}
k
:=
n
.
Key
()
if
_
,
found
:=
t
.
seen
[
string
(
k
)];
found
{
return
true
,
nil
}
...
...
utils/diff.go
View file @
1268b9cc
...
...
@@ -5,9 +5,10 @@ import (
"fmt"
"path"
key
"github.com/ipfs/go-ipfs/blocks/key"
dag
"github.com/ipfs/go-ipfs/merkledag"
context
"gx/ipfs/QmZy2y8t9zQH2a1b8q2ZSLKp17ATuJoCNxxyMFG5qFExpt/go-net/context"
cid
"gx/ipfs/QmfSc2xehWmWLnwwYR91Y8QF4xdASypTFVknutoKQS3GHp/go-cid"
)
const
(
...
...
@@ -19,18 +20,18 @@ const (
type
Change
struct
{
Type
int
Path
string
Before
key
.
Key
After
key
.
Key
Before
*
cid
.
Cid
After
*
cid
.
Cid
}
func
(
c
*
Change
)
String
()
string
{
switch
c
.
Type
{
case
Add
:
return
fmt
.
Sprintf
(
"Added %s at %s"
,
c
.
After
.
B58
String
()
[
:
6
]
,
c
.
Path
)
return
fmt
.
Sprintf
(
"Added %s at %s"
,
c
.
After
.
String
(),
c
.
Path
)
case
Remove
:
return
fmt
.
Sprintf
(
"Removed %s from %s"
,
c
.
Before
.
B58
String
()
[
:
6
]
,
c
.
Path
)
return
fmt
.
Sprintf
(
"Removed %s from %s"
,
c
.
Before
.
String
(),
c
.
Path
)
case
Mod
:
return
fmt
.
Sprintf
(
"Changed %s to %s at %s"
,
c
.
Before
.
B58
String
()
[
:
6
]
,
c
.
After
.
B58
String
()
[
:
6
]
,
c
.
Path
)
return
fmt
.
Sprintf
(
"Changed %s to %s at %s"
,
c
.
Before
.
String
(),
c
.
After
.
String
(),
c
.
Path
)
default
:
panic
(
"nope"
)
}
...
...
@@ -77,21 +78,11 @@ func ApplyChange(ctx context.Context, ds dag.DAGService, nd *dag.Node, cs []*Cha
func
Diff
(
ctx
context
.
Context
,
ds
dag
.
DAGService
,
a
,
b
*
dag
.
Node
)
([]
*
Change
,
error
)
{
if
len
(
a
.
Links
)
==
0
&&
len
(
b
.
Links
)
==
0
{
ak
,
err
:=
a
.
Key
()
if
err
!=
nil
{
return
nil
,
err
}
bk
,
err
:=
b
.
Key
()
if
err
!=
nil
{
return
nil
,
err
}
return
[]
*
Change
{
&
Change
{
Type
:
Mod
,
Before
:
a
k
,
After
:
b
k
,
Before
:
a
.
Cid
()
,
After
:
b
.
Cid
()
,
},
},
nil
}
...
...
@@ -136,14 +127,14 @@ func Diff(ctx context.Context, ds dag.DAGService, a, b *dag.Node) ([]*Change, er
out
=
append
(
out
,
&
Change
{
Type
:
Remove
,
Path
:
lnk
.
Name
,
Before
:
key
.
Key
(
lnk
.
Hash
),
Before
:
cid
.
NewCidV0
(
lnk
.
Hash
),
})
}
for
_
,
lnk
:=
range
clean_b
.
Links
{
out
=
append
(
out
,
&
Change
{
Type
:
Add
,
Path
:
lnk
.
Name
,
After
:
key
.
Key
(
lnk
.
Hash
),
After
:
cid
.
NewCidV0
(
lnk
.
Hash
),
})
}
...
...
utils/utils_test.go
View file @
1268b9cc
...
...
@@ -3,12 +3,12 @@ package dagutils
import
(
"testing"
key
"github.com/ipfs/go-ipfs/blocks/key"
dag
"github.com/ipfs/go-ipfs/merkledag"
mdtest
"github.com/ipfs/go-ipfs/merkledag/test"
path
"github.com/ipfs/go-ipfs/path"
context
"gx/ipfs/QmZy2y8t9zQH2a1b8q2ZSLKp17ATuJoCNxxyMFG5qFExpt/go-net/context"
cid
"gx/ipfs/QmfSc2xehWmWLnwwYR91Y8QF4xdASypTFVknutoKQS3GHp/go-cid"
)
func
TestAddLink
(
t
*
testing
.
T
)
{
...
...
@@ -31,17 +31,13 @@ func TestAddLink(t *testing.T) {
t
.
Fatal
(
err
)
}
fnpkey
,
err
:=
fnprime
.
Key
()
if
err
!=
nil
{
t
.
Fatal
(
err
)
}
if
fnpkey
!=
fk
{
fnpkey
:=
fnprime
.
Cid
()
if
!
fnpkey
.
Equals
(
fk
)
{
t
.
Fatal
(
"wrong child node found!"
)
}
}
func
assertNodeAtPath
(
t
*
testing
.
T
,
ds
dag
.
DAGService
,
root
*
dag
.
Node
,
pth
string
,
exp
key
.
Key
)
{
func
assertNodeAtPath
(
t
*
testing
.
T
,
ds
dag
.
DAGService
,
root
*
dag
.
Node
,
pth
string
,
exp
*
cid
.
Cid
)
{
parts
:=
path
.
SplitList
(
pth
)
cur
:=
root
for
_
,
e
:=
range
parts
{
...
...
@@ -53,12 +49,8 @@ func assertNodeAtPath(t *testing.T, ds dag.DAGService, root *dag.Node, pth strin
cur
=
nxt
}
curk
,
err
:=
cur
.
Key
()
if
err
!=
nil
{
t
.
Fatal
(
err
)
}
if
curk
!=
exp
{
curc
:=
cur
.
Cid
()
if
!
curc
.
Equals
(
exp
)
{
t
.
Fatal
(
"node not as expected at end of path"
)
}
}
...
...
@@ -77,13 +69,10 @@ func TestInsertNode(t *testing.T) {
testInsert
(
t
,
e
,
""
,
"bar"
,
true
,
"cannot create link with no name!"
)
testInsert
(
t
,
e
,
"////"
,
"slashes"
,
true
,
"cannot create link with no name!"
)
k
,
err
:=
e
.
GetNode
()
.
Key
()
if
err
!=
nil
{
t
.
Fatal
(
err
)
}
c
:=
e
.
GetNode
()
.
Cid
()
if
k
.
B58
String
()
!=
"QmZ8yeT9uD6ouJPNAYt62XffYuXBT6b4mP4obRSE9cJrSt"
{
t
.
Fatal
(
"output was different than expected: "
,
k
)
if
c
.
String
()
!=
"QmZ8yeT9uD6ouJPNAYt62XffYuXBT6b4mP4obRSE9cJrSt"
{
t
.
Fatal
(
"output was different than expected: "
,
c
)
}
}
...
...
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