Commit 31b0ff03 authored by Jeromy's avatar Jeromy

add testing for pins

parent 6458ddcd
......@@ -68,6 +68,7 @@ Use "ipfs help <command>" for more information about a command.
cmdIpfsBlock,
cmdIpfsObject,
cmdIpfsLog,
cmdIpfsPin,
},
Flag: *flag.NewFlagSet("ipfs", flag.ExitOnError),
}
......
......@@ -18,14 +18,34 @@ var cmdIpfsPin = &commander.Command{
Flag: *flag.NewFlagSet("ipfs-pin", flag.ExitOnError),
}
func init() {
cmdIpfsPin.Flag.Bool("r", false, "pin objects recursively")
cmdIpfsPin.Flag.Int("d", 1, "recursive depth")
}
var pinCmd = makeCommand(command{
name: "pin",
args: 1,
flags: []string{"r", "d"},
cmdFn: commands.Pin,
})
var cmdIpfsUnpin = &commander.Command{
UsageLine: "unpin",
Short: "unpin an ipfs object from local storage.",
Long: `ipfs unpin <ipfs-path> - unpin ipfs object from local storage.
Removes the pin from the given object allowing it to be garbage
collected if needed.
`,
Run: unpinCmd,
Flag: *flag.NewFlagSet("ipfs-unpin", flag.ExitOnError),
}
var unpinCmd = makeCommand(command{
name: "unpin",
args: 1,
flags: []string{"r", "d"},
cmdFn: commands.Unpin,
})
func init() {
cmdIpfsPin.Flag.Bool("r", false, "pin objects recursively")
cmdIpfsPin.Flag.Int("d", 1, "recursive depth")
cmdIpfsUnpin.Flag.Bool("r", false, "unpin objects recursively")
}
......@@ -117,6 +117,6 @@ func addNode(n *core.IpfsNode, nd *dag.Node, fpath string, out io.Writer) error
// output that we've added this node
fmt.Fprintf(out, "added %s %s\n", k, fpath)
// ensure we keep it. atm no-op
return n.PinDagNodeRecursively(nd, -1)
// ensure we keep it
return n.Pinning.Pin(nd, true)
}
......@@ -29,7 +29,27 @@ func Pin(n *core.IpfsNode, args []string, opts map[string]interface{}, out io.Wr
return fmt.Errorf("pin error: %v", err)
}
err = n.PinDagNodeRecursively(dagnode, depth)
err = n.Pinning.Pin(dagnode, recursive)
if err != nil {
return fmt.Errorf("pin: %v", err)
}
}
return nil
}
func Unpin(n *core.IpfsNode, args []string, opts map[string]interface{}, out io.Writer) error {
// set recursive flag
recursive, _ := opts["r"].(bool) // false if cast fails.
for _, fn := range args {
dagnode, err := n.Resolver.ResolvePath(fn)
if err != nil {
return fmt.Errorf("pin error: %v", err)
}
k, _ := dagnode.Key()
err = n.Pinning.Unpin(k, recursive)
if err != nil {
return fmt.Errorf("pin: %v", err)
}
......
......@@ -22,6 +22,7 @@ import (
netservice "github.com/jbenet/go-ipfs/net/service"
path "github.com/jbenet/go-ipfs/path"
peer "github.com/jbenet/go-ipfs/peer"
pin "github.com/jbenet/go-ipfs/pin"
routing "github.com/jbenet/go-ipfs/routing"
dht "github.com/jbenet/go-ipfs/routing/dht"
u "github.com/jbenet/go-ipfs/util"
......@@ -67,6 +68,9 @@ type IpfsNode struct {
// the diagnostics service
Diagnostics *diag.Diagnostics
// the pinning manager
Pinning pin.Pinner
}
// NewIpfsNode constructs a new IpfsNode based on the given config.
......@@ -159,6 +163,10 @@ func NewIpfsNode(cfg *config.Config, online bool) (*IpfsNode, error) {
dag := &merkledag.DAGService{Blocks: bs}
ns := namesys.NewNameSystem(route)
p, err := pin.LoadPinner(d, dag)
if err != nil {
p = pin.NewPinner(d, dag)
}
success = true
return &IpfsNode{
......@@ -174,6 +182,7 @@ func NewIpfsNode(cfg *config.Config, online bool) (*IpfsNode, error) {
Namesys: ns,
Diagnostics: diagnostics,
Network: network,
Pinning: p,
}, nil
}
......@@ -243,14 +252,3 @@ func initConnections(ctx context.Context, cfg *config.Config, pstore peer.Peerst
}
}
}
// PinDagNode ensures a given node is stored persistently locally
func (n *IpfsNode) PinDagNode(nd *merkledag.Node) error {
return n.PinDagNodeRecursively(nd, 1)
}
// PinDagNodeRecursively ensures a given node is stored persistently locally
func (n *IpfsNode) PinDagNodeRecursively(nd *merkledag.Node, depth int) error {
log.Debug("Pinning node recursively. Currently No-Op")
return nil
}
......@@ -139,6 +139,8 @@ func (dl *DaemonListener) handleConnection(conn manet.Conn) {
err = commands.BlockPut(dl.node, command.Args, command.Opts, conn)
case "log":
err = commands.Log(dl.node, command.Args, command.Opts, conn)
case "unpin":
err = commands.Unpin(dl.node, command.Args, command.Opts, conn)
default:
err = fmt.Errorf("Invalid Command: '%s'", command.Command)
}
......
......@@ -15,6 +15,7 @@ var directPinDatastoreKey = ds.NewKey("/local/pins/direct/keys")
var indirectPinDatastoreKey = ds.NewKey("/local/pins/indirect/keys")
type Pinner interface {
IsPinned(util.Key) bool
Pin(*mdag.Node, bool) error
Unpin(util.Key, bool) error
Flush() error
......@@ -138,7 +139,7 @@ func (p *pinner) IsPinned(key util.Key) bool {
p.indirPin.HasKey(key)
}
func LoadPinner(d ds.Datastore) (Pinner, error) {
func LoadPinner(d ds.Datastore, dserv *mdag.DAGService) (Pinner, error) {
p := new(pinner)
var err error
......@@ -156,6 +157,9 @@ func LoadPinner(d ds.Datastore) (Pinner, error) {
return nil, err
}
p.dserv = dserv
p.dstore = d
return p, nil
}
......
package pin
import (
"testing"
"github.com/jbenet/go-ipfs/Godeps/_workspace/src/github.com/jbenet/datastore.go"
bs "github.com/jbenet/go-ipfs/blockservice"
mdag "github.com/jbenet/go-ipfs/merkledag"
"github.com/jbenet/go-ipfs/util"
)
func randNode() (*mdag.Node, util.Key) {
nd := new(mdag.Node)
nd.Data = make([]byte, 32)
util.NewFastRand().Read(nd.Data)
k, _ := nd.Key()
return nd, k
}
func TestPinnerBasic(t *testing.T) {
dstore := datastore.NewMapDatastore()
bserv, err := bs.NewBlockService(dstore, nil)
if err != nil {
t.Fatal(err)
}
dserv := &mdag.DAGService{bserv}
p := NewPinner(dstore, dserv)
a, ak := randNode()
// Pin A{}
err = p.Pin(a, false)
if err != nil {
t.Fatal(err)
}
if !p.IsPinned(ak) {
t.Fatal("Failed to find key")
}
b, _ := randNode()
err = b.AddNodeLink("child", a)
if err != nil {
t.Fatal(err)
}
c, ck := randNode()
err = b.AddNodeLink("otherchild", c)
if err != nil {
t.Fatal(err)
}
// recursively pin B{A,C}
err = p.Pin(b, true)
if err != nil {
t.Fatal(err)
}
if !p.IsPinned(ck) {
t.Fatal("Child of recursively pinned node not found")
}
bk, _ := b.Key()
if !p.IsPinned(bk) {
t.Fatal("Recursively pinned node not found..")
}
d, _ := randNode()
d.AddNodeLink("a", a)
d.AddNodeLink("c", c)
e, ek := randNode()
d.AddNodeLink("e", e)
// Must be in dagserv for unpin to work
err = dserv.AddRecursive(d)
if err != nil {
t.Fatal(err)
}
// Add D{A,C,E}
err = p.Pin(d, true)
if err != nil {
t.Fatal(err)
}
if !p.IsPinned(ek) {
t.Fatal(err)
}
dk, _ := d.Key()
if !p.IsPinned(dk) {
t.Fatal("pinned node not found.")
}
// Test recursive unpin
err = p.Unpin(dk, true)
if err != nil {
t.Fatal(err)
}
// c should still be pinned under b
if !p.IsPinned(ck) {
t.Fatal("Recursive unpin fail.")
}
err = p.Flush()
if err != nil {
t.Fatal(err)
}
np, err := LoadPinner(dstore, dserv)
if err != nil {
t.Fatal(err)
}
// Test directly pinned
if !np.IsPinned(ak) {
t.Fatal("Could not find pinned node!")
}
// Test indirectly pinned
if !np.IsPinned(ck) {
t.Fatal("could not find indirectly pinned node")
}
// Test recursively pinned
if !np.IsPinned(bk) {
t.Fatal("could not find recursively pinned node")
}
}
Markdown is supported
0% or .
You are about to add 0 people to the discussion. Proceed with caution.
Finish editing this message first!
Please register or to comment