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.