@cryptotaxi247 / kubo / commits / f63d45ca5

merkledag: split off node.go

Juan Batiz-Benet committed Jan 7, 2015 at 02:15 UTC f63d45ca56733c4b899ab97483ebc01fbd592770
2 files changed +188 -181
merkledag/merkledag.go
-181
@@ -9,7 +9,6 @@ import (
9
10 "github.com/jbenet/go-ipfs/Godeps/_workspace/src/code.google.com/p/go.net/context"
11
12 - mh "github.com/jbenet/go-ipfs/Godeps/_workspace/src/github.com/jbenet/go-multihash"
12 blocks "github.com/jbenet/go-ipfs/blocks"
13 bserv "github.com/jbenet/go-ipfs/blockservice"
14 u "github.com/jbenet/go-ipfs/util"
@@ -18,11 +17,6 @@ import (
17 var log = u.Logger("merkledag")
18 var ErrNotFound = fmt.Errorf("merkledag: not found")
19
21 -// NodeMap maps u.Keys to Nodes.
22 -// We cannot use []byte/Multihash for keys :(
23 -// so have to convert Multihash bytes to string (u.Key)
24 -type NodeMap map[u.Key]*Node
25 -
20 // DAGService is an IPFS Merkle DAG service.
21 type DAGService interface {
22 Add(*Node) (u.Key, error)
@@ -39,181 +33,6 @@ func NewDAGService(bs *bserv.BlockService) DAGService {
33 return &dagService{bs}
34 }
35
42 -// Node represents a node in the IPFS Merkle DAG.
43 -// nodes have opaque data and a set of navigable links.
44 -type Node struct {
45 - Links []*Link
46 - Data []byte
47 -
48 - // cache encoded/marshaled value
49 - encoded []byte
50 -
51 - cached mh.Multihash
52 -}
53 -
54 -// NodeStat is a statistics object for a Node. Mostly sizes.
55 -type NodeStat struct {
56 - NumLinks int // number of links in link table
57 - BlockSize int // size of the raw data
58 - LinksSize int // size of the links segment
59 - DataSize int // size of the data segment
60 - CumulativeSize int // cumulatie size of object + all it references
61 -}
62 -
63 -func (ns NodeStat) String() string {
64 - f := "NodeStat{NumLinks: %d, BlockSize: %d, LinksSize: %d, DataSize: %d, CumulativeSize: %d}"
65 - return fmt.Sprintf(f, ns.NumLinks, ns.BlockSize, ns.LinksSize, ns.DataSize, ns.CumulativeSize)
66 -}
67 -
68 -// Link represents an IPFS Merkle DAG Link between Nodes.
69 -type Link struct {
70 - // utf string name. should be unique per object
71 - Name string // utf8
72 -
73 - // cumulative size of target object
74 - Size uint64
75 -
76 - // multihash of the target object
77 - Hash mh.Multihash
78 -
79 - // a ptr to the actual node for graph manipulation
80 - Node *Node
81 -}
82 -
83 -type LinkSlice []*Link
84 -
85 -func (ls LinkSlice) Len() int { return len(ls) }
86 -func (ls LinkSlice) Swap(a, b int) { ls[a], ls[b] = ls[b], ls[a] }
87 -func (ls LinkSlice) Less(a, b int) bool { return ls[a].Name < ls[b].Name }
88 -
89 -// MakeLink creates a link to the given node
90 -func MakeLink(n *Node) (*Link, error) {
91 - s, err := n.Size()
92 - if err != nil {
93 - return nil, err
94 - }
95 -
96 - h, err := n.Multihash()
97 - if err != nil {
98 - return nil, err
99 - }
100 - return &Link{
101 - Size: s,
102 - Hash: h,
103 - }, nil
104 -}
105 -
106 -// GetNode returns the MDAG Node that this link points to
107 -func (l *Link) GetNode(serv DAGService) (*Node, error) {
108 - if l.Node != nil {
109 - return l.Node, nil
110 - }
111 -
112 - return serv.Get(u.Key(l.Hash))
113 -}
114 -
115 -// AddNodeLink adds a link to another node.
116 -func (n *Node) AddNodeLink(name string, that *Node) error {
117 - lnk, err := MakeLink(that)
118 - if err != nil {
119 - return err
120 - }
121 - lnk.Name = name
122 - lnk.Node = that
123 -
124 - n.Links = append(n.Links, lnk)
125 - return nil
126 -}
127 -
128 -// AddNodeLink adds a link to another node. without keeping a reference to
129 -// the child node
130 -func (n *Node) AddNodeLinkClean(name string, that *Node) error {
131 - lnk, err := MakeLink(that)
132 - if err != nil {
133 - return err
134 - }
135 - lnk.Name = name
136 -
137 - n.Links = append(n.Links, lnk)
138 - return nil
139 -}
140 -
141 -// Remove a link on this node by the given name
142 -func (n *Node) RemoveNodeLink(name string) error {
143 - for i, l := range n.Links {
144 - if l.Name == name {
145 - n.Links = append(n.Links[:i], n.Links[i+1:]...)
146 - return nil
147 - }
148 - }
149 - return ErrNotFound
150 -}
151 -
152 -// Copy returns a copy of the node.
153 -// NOTE: does not make copies of Node objects in the links.
154 -func (n *Node) Copy() *Node {
155 - nnode := new(Node)
156 - nnode.Data = make([]byte, len(n.Data))
157 - copy(nnode.Data, n.Data)
158 -
159 - nnode.Links = make([]*Link, len(n.Links))
160 - copy(nnode.Links, n.Links)
161 - return nnode
162 -}
163 -
164 -// Size returns the total size of the data addressed by node,
165 -// including the total sizes of references.
166 -func (n *Node) Size() (uint64, error) {
167 - b, err := n.Encoded(false)
168 - if err != nil {
169 - return 0, err
170 - }
171 -
172 - s := uint64(len(b))
173 - for _, l := range n.Links {
174 - s += l.Size
175 - }
176 - return s, nil
177 -}
178 -
179 -// Stat returns statistics on the node.
180 -func (n *Node) Stat() (NodeStat, error) {
181 - enc, err := n.Encoded(false)
182 - if err != nil {
183 - return NodeStat{}, err
184 - }
185 -
186 - cumSize, err := n.Size()
187 - if err != nil {
188 - return NodeStat{}, err
189 - }
190 -
191 - return NodeStat{
192 - NumLinks: len(n.Links),
193 - BlockSize: len(enc),
194 - LinksSize: len(enc) - len(n.Data), // includes framing.
195 - DataSize: len(n.Data),
196 - CumulativeSize: int(cumSize),
197 - }, nil
198 -}
199 -
200 -// Multihash hashes the encoded data of this node.
201 -func (n *Node) Multihash() (mh.Multihash, error) {
202 - // Note: Encoded generates the hash and puts it in n.cached.
203 - _, err := n.Encoded(false)
204 - if err != nil {
205 - return nil, err
206 - }
207 -
208 - return n.cached, nil
209 -}
210 -
211 -// Key returns the Multihash as a key, for maps.
212 -func (n *Node) Key() (u.Key, error) {
213 - h, err := n.Multihash()
214 - return u.Key(h), err
215 -}
216 -
36 // dagService is an IPFS Merkle DAG service.
37 // - the root is virtual (like a forest)
38 // - stores nodes' data in a BlockService
merkledag/node.go new
+188
@@ -0,0 +1,188 @@
1 +package merkledag
2 +
3 +import (
4 + "fmt"
5 +
6 + mh "github.com/jbenet/go-ipfs/Godeps/_workspace/src/github.com/jbenet/go-multihash"
7 + u "github.com/jbenet/go-ipfs/util"
8 +)
9 +
10 +// NodeMap maps u.Keys to Nodes.
11 +// We cannot use []byte/Multihash for keys :(
12 +// so have to convert Multihash bytes to string (u.Key)
13 +type NodeMap map[u.Key]*Node
14 +
15 +// Node represents a node in the IPFS Merkle DAG.
16 +// nodes have opaque data and a set of navigable links.
17 +type Node struct {
18 + Links []*Link
19 + Data []byte
20 +
21 + // cache encoded/marshaled value
22 + encoded []byte
23 +
24 + cached mh.Multihash
25 +}
26 +
27 +// NodeStat is a statistics object for a Node. Mostly sizes.
28 +type NodeStat struct {
29 + NumLinks int // number of links in link table
30 + BlockSize int // size of the raw data
31 + LinksSize int // size of the links segment
32 + DataSize int // size of the data segment
33 + CumulativeSize int // cumulatie size of object + all it references
34 +}
35 +
36 +func (ns NodeStat) String() string {
37 + f := "NodeStat{NumLinks: %d, BlockSize: %d, LinksSize: %d, DataSize: %d, CumulativeSize: %d}"
38 + return fmt.Sprintf(f, ns.NumLinks, ns.BlockSize, ns.LinksSize, ns.DataSize, ns.CumulativeSize)
39 +}
40 +
41 +// Link represents an IPFS Merkle DAG Link between Nodes.
42 +type Link struct {
43 + // utf string name. should be unique per object
44 + Name string // utf8
45 +
46 + // cumulative size of target object
47 + Size uint64
48 +
49 + // multihash of the target object
50 + Hash mh.Multihash
51 +
52 + // a ptr to the actual node for graph manipulation
53 + Node *Node
54 +}
55 +
56 +type LinkSlice []*Link
57 +
58 +func (ls LinkSlice) Len() int { return len(ls) }
59 +func (ls LinkSlice) Swap(a, b int) { ls[a], ls[b] = ls[b], ls[a] }
60 +func (ls LinkSlice) Less(a, b int) bool { return ls[a].Name < ls[b].Name }
61 +
62 +// MakeLink creates a link to the given node
63 +func MakeLink(n *Node) (*Link, error) {
64 + s, err := n.Size()
65 + if err != nil {
66 + return nil, err
67 + }
68 +
69 + h, err := n.Multihash()
70 + if err != nil {
71 + return nil, err
72 + }
73 + return &Link{
74 + Size: s,
75 + Hash: h,
76 + }, nil
77 +}
78 +
79 +// GetNode returns the MDAG Node that this link points to
80 +func (l *Link) GetNode(serv DAGService) (*Node, error) {
81 + if l.Node != nil {
82 + return l.Node, nil
83 + }
84 +
85 + return serv.Get(u.Key(l.Hash))
86 +}
87 +
88 +// AddNodeLink adds a link to another node.
89 +func (n *Node) AddNodeLink(name string, that *Node) error {
90 + lnk, err := MakeLink(that)
91 + if err != nil {
92 + return err
93 + }
94 + lnk.Name = name
95 + lnk.Node = that
96 +
97 + n.Links = append(n.Links, lnk)
98 + return nil
99 +}
100 +
101 +// AddNodeLink adds a link to another node. without keeping a reference to
102 +// the child node
103 +func (n *Node) AddNodeLinkClean(name string, that *Node) error {
104 + lnk, err := MakeLink(that)
105 + if err != nil {
106 + return err
107 + }
108 + lnk.Name = name
109 +
110 + n.Links = append(n.Links, lnk)
111 + return nil
112 +}
113 +
114 +// Remove a link on this node by the given name
115 +func (n *Node) RemoveNodeLink(name string) error {
116 + for i, l := range n.Links {
117 + if l.Name == name {
118 + n.Links = append(n.Links[:i], n.Links[i+1:]...)
119 + return nil
120 + }
121 + }
122 + return ErrNotFound
123 +}
124 +
125 +// Copy returns a copy of the node.
126 +// NOTE: does not make copies of Node objects in the links.
127 +func (n *Node) Copy() *Node {
128 + nnode := new(Node)
129 + nnode.Data = make([]byte, len(n.Data))
130 + copy(nnode.Data, n.Data)
131 +
132 + nnode.Links = make([]*Link, len(n.Links))
133 + copy(nnode.Links, n.Links)
134 + return nnode
135 +}
136 +
137 +// Size returns the total size of the data addressed by node,
138 +// including the total sizes of references.
139 +func (n *Node) Size() (uint64, error) {
140 + b, err := n.Encoded(false)
141 + if err != nil {
142 + return 0, err
143 + }
144 +
145 + s := uint64(len(b))
146 + for _, l := range n.Links {
147 + s += l.Size
148 + }
149 + return s, nil
150 +}
151 +
152 +// Stat returns statistics on the node.
153 +func (n *Node) Stat() (NodeStat, error) {
154 + enc, err := n.Encoded(false)
155 + if err != nil {
156 + return NodeStat{}, err
157 + }
158 +
159 + cumSize, err := n.Size()
160 + if err != nil {
161 + return NodeStat{}, err
162 + }
163 +
164 + return NodeStat{
165 + NumLinks: len(n.Links),
166 + BlockSize: len(enc),
167 + LinksSize: len(enc) - len(n.Data), // includes framing.
168 + DataSize: len(n.Data),
169 + CumulativeSize: int(cumSize),
170 + }, nil
171 +}
172 +
173 +// Multihash hashes the encoded data of this node.
174 +func (n *Node) Multihash() (mh.Multihash, error) {
175 + // Note: Encoded generates the hash and puts it in n.cached.
176 + _, err := n.Encoded(false)
177 + if err != nil {
178 + return nil, err
179 + }
180 +
181 + return n.cached, nil
182 +}
183 +
184 +// Key returns the Multihash as a key, for maps.
185 +func (n *Node) Key() (u.Key, error) {
186 + h, err := n.Multihash()
187 + return u.Key(h), err
188 +}