@cryptotaxi247 / kubo / commits / 7f5e13716

writes to ipns work if the top object is the written file (no directories yet!)

Jeromy committed Sep 25, 2014 at 22:00 UTC 7f5e13716deedcc9d040739cf6b797e4697be1f6
3 files changed +118 -4
core/core.go
+5
@@ -62,6 +62,9 @@ type IpfsNode struct {
62
63 // the name system, resolves paths to hashes
64 Namesys namesys.Resolver
65 +
66 + // the routing publisher
67 + Publisher *namesys.IpnsPublisher
68 }
69
70 // NewIpfsNode constructs a new IpfsNode based on the given config.
@@ -144,6 +147,7 @@ func NewIpfsNode(cfg *config.Config, online bool) (*IpfsNode, error) {
147
148 dag := &merkledag.DAGService{Blocks: bs}
149 resolve := namesys.NewMasterResolver(route, dag)
150 + publisher := namesys.NewPublisher(dag, route)
151
152 success = true
153 return &IpfsNode{
@@ -157,6 +161,7 @@ func NewIpfsNode(cfg *config.Config, online bool) (*IpfsNode, error) {
161 Identity: local,
162 Routing: route,
163 Namesys: resolve,
164 + Publisher: publisher,
165 }, nil
166 }
167
fuse/ipns/ipns_unix.go
+112 -3
@@ -11,11 +11,14 @@ import (
11 "syscall"
12 "time"
13
14 + "bytes"
15 +
16 "bazil.org/fuse"
17 "bazil.org/fuse/fs"
18 "code.google.com/p/goprotobuf/proto"
19 "github.com/jbenet/go-ipfs/core"
20 ci "github.com/jbenet/go-ipfs/crypto"
21 + imp "github.com/jbenet/go-ipfs/importer"
22 mdag "github.com/jbenet/go-ipfs/merkledag"
23 u "github.com/jbenet/go-ipfs/util"
24 "github.com/op/go-logging"
@@ -63,6 +66,33 @@ func CreateRoot(n *core.IpfsNode, keys []ci.PrivKey, ipfsroot string) (*Root, er
66 root.LocalLink = &Link{u.Key(hash).Pretty()}
67 }
68
69 + for _, k := range keys {
70 + hash, err := k.GetPublic().Hash()
71 + if err != nil {
72 + log.Error("failed to hash public key.")
73 + continue
74 + }
75 + name := u.Key(hash).Pretty()
76 + nd := new(Node)
77 + nd.Ipfs = n
78 + nd.key = k
79 +
80 + pointsTo, err := n.Namesys.Resolve(name)
81 + if err != nil {
82 + log.Warning("Could not resolve value for local ipns entry")
83 + continue
84 + }
85 +
86 + node, err := n.Resolver.ResolvePath(pointsTo)
87 + if err != nil {
88 + log.Warning("Failed to resolve value from ipns entry in ipfs")
89 + continue
90 + }
91 +
92 + nd.Nd = node
93 + root.LocalDirs[name] = nd
94 + }
95 +
96 return root, nil
97 }
98
@@ -147,10 +177,17 @@ func (r *Root) ReadDir(intr fs.Intr) ([]fuse.Dirent, fuse.Error) {
177 // Node is the core object representing a filesystem tree node.
178 type Node struct {
179 nsRoot *Node
180 +
181 + // Private keys held by nodes at the root of a keyspace
182 + key ci.PrivKey
183 +
184 Ipfs *core.IpfsNode
185 Nd *mdag.Node
186 fd *mdag.DagReader
187 cached *mdag.PBData
188 +
189 + dataBuf *bytes.Buffer
190 + changed bool
191 }
192
193 func (s *Node) loadData() error {
@@ -172,7 +209,7 @@ func (s *Node) Attr() fuse.Attr {
209 u.DOut("this is a file.\n")
210 size, _ := s.Nd.Size()
211 return fuse.Attr{
175 - Mode: 0444,
212 + Mode: 0666,
213 Size: uint64(size),
214 Blocks: uint64(len(s.Nd.Links)),
215 }
@@ -184,14 +221,25 @@ func (s *Node) Attr() fuse.Attr {
221
222 // Lookup performs a lookup under this node.
223 func (s *Node) Lookup(name string, intr fs.Intr) (fs.Node, fuse.Error) {
187 - u.DOut("Lookup '%s'\n", name)
224 + log.Debug("ipns node Lookup '%s'", name)
225 nd, err := s.Ipfs.Resolver.ResolveLinks(s.Nd, []string{name})
226 if err != nil {
227 // todo: make this error more versatile.
228 return nil, fuse.ENOENT
229 }
230
194 - return &Node{Ipfs: s.Ipfs, Nd: nd}, nil
231 + child := &Node{
232 + Ipfs: s.Ipfs,
233 + Nd: nd,
234 + }
235 +
236 + if s.nsRoot == nil {
237 + child.nsRoot = s
238 + } else {
239 + child.nsRoot = s.nsRoot
240 + }
241 +
242 + return child, nil
243 }
244
245 // ReadDir reads the link structure as directory entries
@@ -224,6 +272,67 @@ func (s *Node) ReadAll(intr fs.Intr) ([]byte, fuse.Error) {
272 return ioutil.ReadAll(r)
273 }
274
275 +func (n *Node) Write(req *fuse.WriteRequest, resp *fuse.WriteResponse, intr fs.Intr) fuse.Error {
276 + if n.dataBuf == nil {
277 + n.dataBuf = new(bytes.Buffer)
278 + }
279 + log.Debug("ipns Node Write: flags = %s, offset = %d, size = %d", req.Flags.String(), req.Offset, len(req.Data))
280 + if req.Offset == 0 {
281 + n.dataBuf.Reset()
282 + n.dataBuf.Write(req.Data)
283 + n.changed = true
284 + resp.Size = len(req.Data)
285 + } else {
286 + log.Error("Unhandled write to offset!")
287 + }
288 + return nil
289 +}
290 +
291 +func (n *Node) Flush(req *fuse.FlushRequest, intr fs.Intr) fuse.Error {
292 + log.Debug("Got flush request!")
293 +
294 + if n.changed {
295 + //TODO:
296 + // This operation holds everything in memory,
297 + // should be changed to stream the block creation/storage
298 + // but for now, since the buf is all in memory anyways...
299 + nnode, err := imp.NewDagFromReader(n.dataBuf)
300 + if err != nil {
301 + log.Error("ipns Flush error: %s", err)
302 + // return fuse.EVERYBAD
303 + return fuse.ENODATA
304 + }
305 +
306 + err = n.Ipfs.DAG.AddRecursive(nnode)
307 + if err != nil {
308 + log.Critical("ipns Dag Add Error: %s", err)
309 + }
310 +
311 + n.Nd = nnode
312 + n.changed = false
313 + n.dataBuf = nil
314 +
315 + ndkey, err := nnode.Key()
316 + if err != nil {
317 + log.Error("getKey error: %s", err)
318 + // return fuse.ETHISREALLYSUCKS
319 + return fuse.ENODATA
320 + }
321 + log.Debug("Publishing changes!")
322 +
323 + err = n.Ipfs.Publisher.Publish(n.key, ndkey)
324 + if err != nil {
325 + log.Error("ipns Publish Failed: %s", err)
326 + }
327 + }
328 + return nil
329 +}
330 +
331 +func (n *Node) Fsync(req *fuse.FsyncRequest, intr fs.Intr) fuse.Error {
332 + log.Debug("Got fsync request!")
333 + return nil
334 +}
335 +
336 // Mount mounts an IpfsNode instance at a particular path. It
337 // serves until the process receives exit signals (to Unmount).
338 func Mount(ipfs *core.IpfsNode, fpath string, ipfspath string) error {
routing/dht/routing.go
+1 -1
@@ -103,7 +103,7 @@ func (dht *IpfsDHT) Provide(ctx context.Context, key u.Key) error {
103 dht.providers.AddProvider(key, dht.self)
104 peers := dht.routingTables[0].NearestPeers(kb.ConvertKey(key), PoolSize)
105 if len(peers) == 0 {
106 - return kb.ErrLookupFailure
106 + return nil
107 }
108
109 //TODO FIX: this doesn't work! it needs to be sent to the actual nearest peers.