func (st *Store) pinOp(repoPath string, doUnpin bool) error { node, err := st.fs.LookupNode(repoPath) if err != nil { return err } var pinMe []Node err = Walk(node, true, func(child Node) error { if child.GetType() == NodeTypeFile { pinMe = append(pinMe, child) } return nil }) if err != nil { return err } fn := st.IPFS.Pin if doUnpin { fn = st.IPFS.Unpin } var errs util.Errors for _, toPin := range pinMe { if err := fn(toPin.Hash().Multihash); err != nil { errs = append(errs, err) } } return errs.ToErr() }
// Close the complete conversation pool and free resources. func (cp *conversationPool) Close() error { var errs util.Errors // Make sure we kill down the go routines // in newConversationPool to prevent leaks. cp.updateTicker.Stop() cp.mu.Lock() defer cp.mu.Unlock() // Set changeCh to nil, so potential remote // events notice that the pool was closed. close(cp.changeCh) cp.changeCh = nil // Close all conversations. Does not need to be done by Layer. for _, cnv := range cp.open { if err := cnv.Close(); err != nil { errs = append(errs, err) } } // Reset conversations maps: cp.open = make(map[id.ID]Conversation) cp.heartbeat = make(map[id.ID]*ipfsutil.Pinger) return errs.ToErr() }
// Disconnect closes the connection pool and // resets the connector to the state it had after NewConnector(). func (cn *Connector) Disconnect() error { errs := util.Errors{} if err := cn.cp.Close(); err != nil { errs = append(errs, err) } if err := cn.layer.Disconnect(); err != nil { errs = append(errs, err) } return errs.ToErr() }
// broadcast implements the actual network broadcasting. // It just sends the request over all conversations in the pool. func (cn *Connector) broadcast(req *wire.Request) error { var errs util.Errors req.ID = 0 for cnv := range cn.cp.Iter() { if err := cnv.SendAsync(req, nil); err != nil { errs = append(errs, err) } } return errs.ToErr() }
// Remove will purge a file locally on this node. // If `recursive` is true and if `path` is a directory, all files // in it will be removed. If `recursive` is false, ErrNotEmpty will // be returned upon non-empty directories. func (st *Store) Remove(repoPath string, recursive bool) error { st.mu.Lock() defer st.mu.Unlock() repoPath = prefixSlash(repoPath) node, err := st.fs.LookupNode(repoPath) if err != nil { return err } if node.GetType() == NodeTypeDirectory && node.NChildren() > 0 && !recursive { return ErrNotEmpty } toBeRemoved := []Node{} err = Walk(node, true, func(child Node) error { toBeRemoved = append(toBeRemoved, child) return nil }) if err != nil { return err } // Only kill the link of the node to it's parent. If `node` is a directory // it already contains the hashes of it's children. parentNode, err := node.Parent() if err != nil { return err } parent, ok := parentNode.(*Directory) if !ok { return ErrBadNode } if err := parent.RemoveChild(node); err != nil { return err } if err := st.fs.StageNode(parent); err != nil { return err } errs := util.Errors{} for _, child := range toBeRemoved { childPath := NodePath(child) if err = st.makeCheckpointByOwner(child.ID(), child.Hash(), nil, childPath, childPath); err != nil { return err } if child.GetType() == NodeTypeFile { if err := st.IPFS.Unpin(child.Hash().Multihash); err != nil { errs = append(errs, err) } } } return errs.ToErr() }