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-dms3
Commits
ce7ad2e2
Commit
ce7ad2e2
authored
Jan 07, 2015
by
Juan Batiz-Benet
Browse files
Options
Browse Files
Download
Plain Diff
Merge pull request #509 from jbenet/ipfs-object-stat
ipfs object learned stat
parents
f862933c
6b279533
Changes
4
Hide whitespace changes
Inline
Side-by-side
Showing
4 changed files
with
285 additions
and
146 deletions
+285
-146
core/commands/object.go
core/commands/object.go
+61
-0
merkledag/merkledag.go
merkledag/merkledag.go
+0
-146
merkledag/merkledag_test.go
merkledag/merkledag_test.go
+36
-0
merkledag/node.go
merkledag/node.go
+188
-0
No files found.
core/commands/object.go
View file @
ce7ad2e2
...
...
@@ -4,6 +4,7 @@ import (
"bytes"
"encoding/json"
"errors"
"fmt"
"io"
"io/ioutil"
"strings"
...
...
@@ -36,6 +37,7 @@ ipfs object get <key> - Get the DAG node named by <key>
ipfs object put <data> <encoding> - Stores input, outputs its key
ipfs object data <key> - Outputs raw bytes in an object
ipfs object links <key> - Outputs links pointed to by object
ipfs object stat <key> - Outputs statistics of object
`
,
},
...
...
@@ -44,6 +46,7 @@ ipfs object links <key> - Outputs links pointed to by object
"links"
:
objectLinksCmd
,
"get"
:
objectGetCmd
,
"put"
:
objectPutCmd
,
"stat"
:
objectStatCmd
,
},
}
...
...
@@ -180,6 +183,64 @@ This command outputs data in the following encodings:
},
}
var
objectStatCmd
=
&
cmds
.
Command
{
Helptext
:
cmds
.
HelpText
{
Tagline
:
"Get stats for the DAG node named by <key>"
,
ShortDescription
:
`
'ipfs object stat' is a plumbing command to print DAG node statistics.
<key> is a base58 encoded multihash. It outputs to stdout:
NumLinks int number of links in link table
BlockSize int size of the raw, encoded data
LinksSize int size of the links segment
DataSize int size of the data segment
CumulativeSize int cumulative size of object and its references
`
,
},
Arguments
:
[]
cmds
.
Argument
{
cmds
.
StringArg
(
"key"
,
true
,
false
,
"Key of the object to retrieve (in base58-encoded multihash format)"
),
},
Run
:
func
(
req
cmds
.
Request
)
(
interface
{},
error
)
{
n
,
err
:=
req
.
Context
()
.
GetNode
()
if
err
!=
nil
{
return
nil
,
err
}
key
:=
req
.
Arguments
()[
0
]
object
,
err
:=
objectGet
(
n
,
key
)
if
err
!=
nil
{
return
nil
,
err
}
ns
,
err
:=
object
.
Stat
()
if
err
!=
nil
{
return
nil
,
err
}
return
ns
,
nil
},
Type
:
dag
.
NodeStat
{},
Marshalers
:
cmds
.
MarshalerMap
{
cmds
.
Text
:
func
(
res
cmds
.
Response
)
(
io
.
Reader
,
error
)
{
ns
:=
res
.
Output
()
.
(
dag
.
NodeStat
)
var
buf
bytes
.
Buffer
w
:=
func
(
s
string
,
n
int
)
{
buf
.
Write
([]
byte
(
fmt
.
Sprintf
(
"%s: %d
\n
"
,
s
,
n
)))
}
w
(
"NumLinks"
,
ns
.
NumLinks
)
w
(
"BlockSize"
,
ns
.
BlockSize
)
w
(
"LinksSize"
,
ns
.
LinksSize
)
w
(
"DataSize"
,
ns
.
DataSize
)
w
(
"CumulativeSize"
,
ns
.
CumulativeSize
)
return
&
buf
,
nil
},
},
}
var
objectPutCmd
=
&
cmds
.
Command
{
Helptext
:
cmds
.
HelpText
{
Tagline
:
"Stores input as a DAG object, outputs its key"
,
...
...
merkledag/merkledag.go
View file @
ce7ad2e2
...
...
@@ -9,7 +9,6 @@ import (
"github.com/jbenet/go-ipfs/Godeps/_workspace/src/code.google.com/p/go.net/context"
mh
"github.com/jbenet/go-ipfs/Godeps/_workspace/src/github.com/jbenet/go-multihash"
blocks
"github.com/jbenet/go-ipfs/blocks"
bserv
"github.com/jbenet/go-ipfs/blockservice"
u
"github.com/jbenet/go-ipfs/util"
...
...
@@ -18,11 +17,6 @@ import (
var
log
=
u
.
Logger
(
"merkledag"
)
var
ErrNotFound
=
fmt
.
Errorf
(
"merkledag: not found"
)
// NodeMap maps u.Keys to Nodes.
// We cannot use []byte/Multihash for keys :(
// so have to convert Multihash bytes to string (u.Key)
type
NodeMap
map
[
u
.
Key
]
*
Node
// DAGService is an IPFS Merkle DAG service.
type
DAGService
interface
{
Add
(
*
Node
)
(
u
.
Key
,
error
)
...
...
@@ -39,146 +33,6 @@ func NewDAGService(bs *bserv.BlockService) DAGService {
return
&
dagService
{
bs
}
}
// Node represents a node in the IPFS Merkle DAG.
// nodes have opaque data and a set of navigable links.
type
Node
struct
{
Links
[]
*
Link
Data
[]
byte
// cache encoded/marshaled value
encoded
[]
byte
cached
mh
.
Multihash
}
// Link represents an IPFS Merkle DAG Link between Nodes.
type
Link
struct
{
// utf string name. should be unique per object
Name
string
// utf8
// cumulative size of target object
Size
uint64
// multihash of the target object
Hash
mh
.
Multihash
// a ptr to the actual node for graph manipulation
Node
*
Node
}
type
LinkSlice
[]
*
Link
func
(
ls
LinkSlice
)
Len
()
int
{
return
len
(
ls
)
}
func
(
ls
LinkSlice
)
Swap
(
a
,
b
int
)
{
ls
[
a
],
ls
[
b
]
=
ls
[
b
],
ls
[
a
]
}
func
(
ls
LinkSlice
)
Less
(
a
,
b
int
)
bool
{
return
ls
[
a
]
.
Name
<
ls
[
b
]
.
Name
}
// MakeLink creates a link to the given node
func
MakeLink
(
n
*
Node
)
(
*
Link
,
error
)
{
s
,
err
:=
n
.
Size
()
if
err
!=
nil
{
return
nil
,
err
}
h
,
err
:=
n
.
Multihash
()
if
err
!=
nil
{
return
nil
,
err
}
return
&
Link
{
Size
:
s
,
Hash
:
h
,
},
nil
}
// GetNode returns the MDAG Node that this link points to
func
(
l
*
Link
)
GetNode
(
serv
DAGService
)
(
*
Node
,
error
)
{
if
l
.
Node
!=
nil
{
return
l
.
Node
,
nil
}
return
serv
.
Get
(
u
.
Key
(
l
.
Hash
))
}
// AddNodeLink adds a link to another node.
func
(
n
*
Node
)
AddNodeLink
(
name
string
,
that
*
Node
)
error
{
lnk
,
err
:=
MakeLink
(
that
)
if
err
!=
nil
{
return
err
}
lnk
.
Name
=
name
lnk
.
Node
=
that
n
.
Links
=
append
(
n
.
Links
,
lnk
)
return
nil
}
// AddNodeLink adds a link to another node. without keeping a reference to
// the child node
func
(
n
*
Node
)
AddNodeLinkClean
(
name
string
,
that
*
Node
)
error
{
lnk
,
err
:=
MakeLink
(
that
)
if
err
!=
nil
{
return
err
}
lnk
.
Name
=
name
n
.
Links
=
append
(
n
.
Links
,
lnk
)
return
nil
}
// Remove a link on this node by the given name
func
(
n
*
Node
)
RemoveNodeLink
(
name
string
)
error
{
for
i
,
l
:=
range
n
.
Links
{
if
l
.
Name
==
name
{
n
.
Links
=
append
(
n
.
Links
[
:
i
],
n
.
Links
[
i
+
1
:
]
...
)
return
nil
}
}
return
ErrNotFound
}
// Copy returns a copy of the node.
// NOTE: does not make copies of Node objects in the links.
func
(
n
*
Node
)
Copy
()
*
Node
{
nnode
:=
new
(
Node
)
nnode
.
Data
=
make
([]
byte
,
len
(
n
.
Data
))
copy
(
nnode
.
Data
,
n
.
Data
)
nnode
.
Links
=
make
([]
*
Link
,
len
(
n
.
Links
))
copy
(
nnode
.
Links
,
n
.
Links
)
return
nnode
}
// Size returns the total size of the data addressed by node,
// including the total sizes of references.
func
(
n
*
Node
)
Size
()
(
uint64
,
error
)
{
b
,
err
:=
n
.
Encoded
(
false
)
if
err
!=
nil
{
return
0
,
err
}
s
:=
uint64
(
len
(
b
))
for
_
,
l
:=
range
n
.
Links
{
s
+=
l
.
Size
}
return
s
,
nil
}
// Multihash hashes the encoded data of this node.
func
(
n
*
Node
)
Multihash
()
(
mh
.
Multihash
,
error
)
{
// Note: Encoded generates the hash and puts it in n.cached.
_
,
err
:=
n
.
Encoded
(
false
)
if
err
!=
nil
{
return
nil
,
err
}
return
n
.
cached
,
nil
}
// Key returns the Multihash as a key, for maps.
func
(
n
*
Node
)
Key
()
(
u
.
Key
,
error
)
{
h
,
err
:=
n
.
Multihash
()
return
u
.
Key
(
h
),
err
}
// dagService is an IPFS Merkle DAG service.
// - the root is virtual (like a forest)
// - stores nodes' data in a BlockService
...
...
merkledag/merkledag_test.go
View file @
ce7ad2e2
...
...
@@ -85,6 +85,8 @@ func TestNode(t *testing.T) {
}
else
{
fmt
.
Println
(
"key: "
,
k
)
}
SubtestNodeStat
(
t
,
n
)
}
printn
(
"beep"
,
n1
)
...
...
@@ -92,6 +94,40 @@ func TestNode(t *testing.T) {
printn
(
"beep boop"
,
n3
)
}
func
SubtestNodeStat
(
t
*
testing
.
T
,
n
*
Node
)
{
enc
,
err
:=
n
.
Encoded
(
true
)
if
err
!=
nil
{
t
.
Error
(
"n.Encoded(true) failed"
)
return
}
cumSize
,
err
:=
n
.
Size
()
if
err
!=
nil
{
t
.
Error
(
"n.Size() failed"
)
return
}
expected
:=
NodeStat
{
NumLinks
:
len
(
n
.
Links
),
BlockSize
:
len
(
enc
),
LinksSize
:
len
(
enc
)
-
len
(
n
.
Data
),
// includes framing.
DataSize
:
len
(
n
.
Data
),
CumulativeSize
:
int
(
cumSize
),
}
actual
,
err
:=
n
.
Stat
()
if
err
!=
nil
{
t
.
Error
(
"n.Stat() failed"
)
return
}
if
expected
!=
actual
{
t
.
Error
(
"n.Stat incorrect.
\n
expect: %s
\n
actual: %s"
,
expected
,
actual
)
}
else
{
fmt
.
Printf
(
"n.Stat correct: %s
\n
"
,
actual
)
}
}
type
devZero
struct
{}
func
(
_
devZero
)
Read
(
b
[]
byte
)
(
int
,
error
)
{
...
...
merkledag/node.go
0 → 100644
View file @
ce7ad2e2
package
merkledag
import
(
"fmt"
mh
"github.com/jbenet/go-ipfs/Godeps/_workspace/src/github.com/jbenet/go-multihash"
u
"github.com/jbenet/go-ipfs/util"
)
// NodeMap maps u.Keys to Nodes.
// We cannot use []byte/Multihash for keys :(
// so have to convert Multihash bytes to string (u.Key)
type
NodeMap
map
[
u
.
Key
]
*
Node
// Node represents a node in the IPFS Merkle DAG.
// nodes have opaque data and a set of navigable links.
type
Node
struct
{
Links
[]
*
Link
Data
[]
byte
// cache encoded/marshaled value
encoded
[]
byte
cached
mh
.
Multihash
}
// NodeStat is a statistics object for a Node. Mostly sizes.
type
NodeStat
struct
{
NumLinks
int
// number of links in link table
BlockSize
int
// size of the raw, encoded data
LinksSize
int
// size of the links segment
DataSize
int
// size of the data segment
CumulativeSize
int
// cumulative size of object and its references
}
func
(
ns
NodeStat
)
String
()
string
{
f
:=
"NodeStat{NumLinks: %d, BlockSize: %d, LinksSize: %d, DataSize: %d, CumulativeSize: %d}"
return
fmt
.
Sprintf
(
f
,
ns
.
NumLinks
,
ns
.
BlockSize
,
ns
.
LinksSize
,
ns
.
DataSize
,
ns
.
CumulativeSize
)
}
// Link represents an IPFS Merkle DAG Link between Nodes.
type
Link
struct
{
// utf string name. should be unique per object
Name
string
// utf8
// cumulative size of target object
Size
uint64
// multihash of the target object
Hash
mh
.
Multihash
// a ptr to the actual node for graph manipulation
Node
*
Node
}
type
LinkSlice
[]
*
Link
func
(
ls
LinkSlice
)
Len
()
int
{
return
len
(
ls
)
}
func
(
ls
LinkSlice
)
Swap
(
a
,
b
int
)
{
ls
[
a
],
ls
[
b
]
=
ls
[
b
],
ls
[
a
]
}
func
(
ls
LinkSlice
)
Less
(
a
,
b
int
)
bool
{
return
ls
[
a
]
.
Name
<
ls
[
b
]
.
Name
}
// MakeLink creates a link to the given node
func
MakeLink
(
n
*
Node
)
(
*
Link
,
error
)
{
s
,
err
:=
n
.
Size
()
if
err
!=
nil
{
return
nil
,
err
}
h
,
err
:=
n
.
Multihash
()
if
err
!=
nil
{
return
nil
,
err
}
return
&
Link
{
Size
:
s
,
Hash
:
h
,
},
nil
}
// GetNode returns the MDAG Node that this link points to
func
(
l
*
Link
)
GetNode
(
serv
DAGService
)
(
*
Node
,
error
)
{
if
l
.
Node
!=
nil
{
return
l
.
Node
,
nil
}
return
serv
.
Get
(
u
.
Key
(
l
.
Hash
))
}
// AddNodeLink adds a link to another node.
func
(
n
*
Node
)
AddNodeLink
(
name
string
,
that
*
Node
)
error
{
lnk
,
err
:=
MakeLink
(
that
)
if
err
!=
nil
{
return
err
}
lnk
.
Name
=
name
lnk
.
Node
=
that
n
.
Links
=
append
(
n
.
Links
,
lnk
)
return
nil
}
// AddNodeLink adds a link to another node. without keeping a reference to
// the child node
func
(
n
*
Node
)
AddNodeLinkClean
(
name
string
,
that
*
Node
)
error
{
lnk
,
err
:=
MakeLink
(
that
)
if
err
!=
nil
{
return
err
}
lnk
.
Name
=
name
n
.
Links
=
append
(
n
.
Links
,
lnk
)
return
nil
}
// Remove a link on this node by the given name
func
(
n
*
Node
)
RemoveNodeLink
(
name
string
)
error
{
for
i
,
l
:=
range
n
.
Links
{
if
l
.
Name
==
name
{
n
.
Links
=
append
(
n
.
Links
[
:
i
],
n
.
Links
[
i
+
1
:
]
...
)
return
nil
}
}
return
ErrNotFound
}
// Copy returns a copy of the node.
// NOTE: does not make copies of Node objects in the links.
func
(
n
*
Node
)
Copy
()
*
Node
{
nnode
:=
new
(
Node
)
nnode
.
Data
=
make
([]
byte
,
len
(
n
.
Data
))
copy
(
nnode
.
Data
,
n
.
Data
)
nnode
.
Links
=
make
([]
*
Link
,
len
(
n
.
Links
))
copy
(
nnode
.
Links
,
n
.
Links
)
return
nnode
}
// Size returns the total size of the data addressed by node,
// including the total sizes of references.
func
(
n
*
Node
)
Size
()
(
uint64
,
error
)
{
b
,
err
:=
n
.
Encoded
(
false
)
if
err
!=
nil
{
return
0
,
err
}
s
:=
uint64
(
len
(
b
))
for
_
,
l
:=
range
n
.
Links
{
s
+=
l
.
Size
}
return
s
,
nil
}
// Stat returns statistics on the node.
func
(
n
*
Node
)
Stat
()
(
NodeStat
,
error
)
{
enc
,
err
:=
n
.
Encoded
(
false
)
if
err
!=
nil
{
return
NodeStat
{},
err
}
cumSize
,
err
:=
n
.
Size
()
if
err
!=
nil
{
return
NodeStat
{},
err
}
return
NodeStat
{
NumLinks
:
len
(
n
.
Links
),
BlockSize
:
len
(
enc
),
LinksSize
:
len
(
enc
)
-
len
(
n
.
Data
),
// includes framing.
DataSize
:
len
(
n
.
Data
),
CumulativeSize
:
int
(
cumSize
),
},
nil
}
// Multihash hashes the encoded data of this node.
func
(
n
*
Node
)
Multihash
()
(
mh
.
Multihash
,
error
)
{
// Note: Encoded generates the hash and puts it in n.cached.
_
,
err
:=
n
.
Encoded
(
false
)
if
err
!=
nil
{
return
nil
,
err
}
return
n
.
cached
,
nil
}
// Key returns the Multihash as a key, for maps.
func
(
n
*
Node
)
Key
()
(
u
.
Key
,
error
)
{
h
,
err
:=
n
.
Multihash
()
return
u
.
Key
(
h
),
err
}
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