// Test writing a file and reading it back func TestIpfsBasicDirRead(t *testing.T) { if testing.Short() { t.SkipNow() } nd, mnt := setupIpfsTest(t, nil) defer mnt.Close() // Make a 'file' fi, data := randObj(t, nd, 10000) k, err := fi.Key() if err != nil { t.Fatal(err) } // Make a directory and put that file in it db := uio.NewDirectory(nd.DAG) err = db.AddChild(nd.Context(), "actual", k) if err != nil { t.Fatal(err) } d1nd := db.GetNode() d1ndk, err := nd.DAG.Add(d1nd) if err != nil { t.Fatal(err) } dirname := path.Join(mnt.Dir, d1ndk.String()) fname := path.Join(dirname, "actual") rbuf, err := ioutil.ReadFile(fname) if err != nil { t.Fatal(err) } dirents, err := ioutil.ReadDir(dirname) if err != nil { t.Fatal(err) } if len(dirents) != 1 { t.Fatal("Bad directory entry count") } if dirents[0].Name() != "actual" { t.Fatal("Bad directory entry") } if !bytes.Equal(rbuf, data) { t.Fatal("Incorrect Read!") } }
func addAssetList(nd *core.IpfsNode, l []string) (*key.Key, error) { dirb := uio.NewDirectory(nd.DAG) for _, p := range l { d, err := Asset(p) if err != nil { return nil, fmt.Errorf("assets: could load Asset '%s': %s", p, err) } s, err := coreunix.Add(nd, bytes.NewBuffer(d)) if err != nil { return nil, fmt.Errorf("assets: could not Add '%s': %s", p, err) } fname := filepath.Base(p) k := key.B58KeyDecode(s) if err := dirb.AddChild(nd.Context(), fname, k); err != nil { return nil, fmt.Errorf("assets: could not add '%s' as a child: %s", fname, err) } } dir := dirb.GetNode() dkey, err := nd.DAG.Add(dir) if err != nil { return nil, fmt.Errorf("assets: DAG.Add(dir) failed: %s", err) } if err := nd.Pinning.Pin(nd.Context(), dir, true); err != nil { return nil, fmt.Errorf("assets: Pinning on init-docu failed: %s", err) } if err := nd.Pinning.Flush(); err != nil { return nil, fmt.Errorf("assets: Pinning flush failed: %s", err) } return &dkey, nil }
func (i *gatewayHandler) putHandler(w http.ResponseWriter, r *http.Request) { // TODO(cryptix): either ask mildred about the flow of this or rewrite it webErrorWithCode(w, "Sorry, PUT is bugged right now, closing request", errors.New("handler disabled"), http.StatusInternalServerError) return urlPath := r.URL.Path pathext := urlPath[5:] var err error if urlPath == ipfsPathPrefix+"QmUNLLsPACCz1vLxQVkXqqLX5R1X345qqfHbsf67hvA3Nn/" { i.putEmptyDirHandler(w, r) return } var newnode *dag.Node if pathext[len(pathext)-1] == '/' { newnode = uio.NewEmptyDirectory() } else { newnode, err = i.newDagFromReader(r.Body) if err != nil { webError(w, "Could not create DAG from request", err, http.StatusInternalServerError) return } } ctx, cancel := context.WithCancel(i.node.Context()) defer cancel() ipfsNode, err := core.Resolve(ctx, i.node, path.Path(urlPath)) if err != nil { // FIXME HTTP error code webError(w, "Could not resolve name", err, http.StatusInternalServerError) return } k, err := ipfsNode.Key() if err != nil { webError(w, "Could not get key from resolved node", err, http.StatusInternalServerError) return } h, components, err := path.SplitAbsPath(path.FromKey(k)) if err != nil { webError(w, "Could not split path", err, http.StatusInternalServerError) return } if len(components) < 1 { err = fmt.Errorf("Cannot override existing object") webError(w, "http gateway", err, http.StatusBadRequest) return } tctx, cancel := context.WithTimeout(ctx, time.Minute) defer cancel() // TODO(cryptix): could this be core.Resolve() too? rootnd, err := i.node.Resolver.DAG.Get(tctx, key.Key(h)) if err != nil { webError(w, "Could not resolve root object", err, http.StatusBadRequest) return } // resolving path components into merkledag nodes. if a component does not // resolve, create empty directories (which will be linked and populated below.) pathNodes, err := i.node.Resolver.ResolveLinks(tctx, rootnd, components[:len(components)-1]) if _, ok := err.(path.ErrNoLink); ok { // Create empty directories, links will be made further down the code for len(pathNodes) < len(components) { pathNodes = append(pathNodes, uio.NewDirectory(i.node.DAG).GetNode()) } } else if err != nil { webError(w, "Could not resolve parent object", err, http.StatusBadRequest) return } for i := len(pathNodes) - 1; i >= 0; i-- { newnode, err = pathNodes[i].UpdateNodeLink(components[i], newnode) if err != nil { webError(w, "Could not update node links", err, http.StatusInternalServerError) return } } if err := i.node.DAG.AddRecursive(newnode); err != nil { webError(w, "Could not add recursively new node", err, http.StatusInternalServerError) return } // Redirect to new path key, err := newnode.Key() if err != nil { webError(w, "Could not get key of new node", err, http.StatusInternalServerError) return } i.addUserHeaders(w) // ok, _now_ write user's headers. w.Header().Set("IPFS-Hash", key.String()) http.Redirect(w, r, ipfsPathPrefix+key.String()+"/"+strings.Join(components, "/"), http.StatusCreated) }
// Perform a large number of concurrent reads to stress the system func TestIpfsStressRead(t *testing.T) { if testing.Short() { t.SkipNow() } nd, mnt := setupIpfsTest(t, nil) defer mnt.Close() var ks []key.Key var paths []string nobj := 50 ndiriter := 50 // Make a bunch of objects for i := 0; i < nobj; i++ { fi, _ := randObj(t, nd, rand.Int63n(50000)) k, err := fi.Key() if err != nil { t.Fatal(err) } ks = append(ks, k) paths = append(paths, k.String()) } // Now make a bunch of dirs for i := 0; i < ndiriter; i++ { db := uio.NewDirectory(nd.DAG) for j := 0; j < 1+rand.Intn(10); j++ { name := fmt.Sprintf("child%d", j) err := db.AddChild(nd.Context(), name, ks[rand.Intn(len(ks))]) if err != nil { t.Fatal(err) } } newdir := db.GetNode() k, err := nd.DAG.Add(newdir) if err != nil { t.Fatal(err) } ks = append(ks, k) npaths := getPaths(t, nd, k.String(), newdir) paths = append(paths, npaths...) } // Now read a bunch, concurrently wg := sync.WaitGroup{} for s := 0; s < 4; s++ { wg.Add(1) go func() { defer wg.Done() for i := 0; i < 2000; i++ { item := paths[rand.Intn(len(paths))] fname := path.Join(mnt.Dir, item) rbuf, err := ioutil.ReadFile(fname) if err != nil { t.Fatal(err) } read, err := coreunix.Cat(nd, item) if err != nil { t.Fatal(err) } data, err := ioutil.ReadAll(read) if err != nil { t.Fatal(err) } if !bytes.Equal(rbuf, data) { t.Fatal("Incorrect Read!") } } }() } wg.Wait() }