Skip to content
This commit does not belong to any branch on this repository, and may belong to a fork outside of the repository.

Commit aa1be6b

Browse files
committedJul 10, 2015
addressing comments from CR
License: MIT Signed-off-by: Jeromy <jeromyj@gmail.com>
1 parent 2d82a20 commit aa1be6b

File tree

4 files changed

+116
-39
lines changed

4 files changed

+116
-39
lines changed
 

‎pin/gc/gc.go

+1-1
Original file line numberDiff line numberDiff line change
@@ -103,7 +103,7 @@ func ColoredSet(pn pin.Pinner, ds dag.DAGService) (key.KeySet, error) {
103103
gcs.Add(k)
104104
}
105105

106-
err = Color(ds, gcs, pn.InternalPins())
106+
err = Descendants(ds, gcs, pn.InternalPins())
107107
if err != nil {
108108
return nil, err
109109
}

‎pin/pin.go

+55-5
Original file line numberDiff line numberDiff line change
@@ -35,7 +35,7 @@ const (
3535
)
3636

3737
type Pinner interface {
38-
IsPinned(key.Key) bool
38+
IsPinned(key.Key) (string, bool, error)
3939
Pin(context.Context, *mdag.Node, bool) error
4040
Unpin(context.Context, key.Key, bool) error
4141

@@ -148,12 +148,38 @@ func (p *pinner) isInternalPin(key key.Key) bool {
148148
}
149149

150150
// IsPinned returns whether or not the given key is pinned
151-
func (p *pinner) IsPinned(key key.Key) bool {
151+
// and an explanation of why its pinned
152+
func (p *pinner) IsPinned(k key.Key) (string, bool, error) {
152153
p.lock.RLock()
153154
defer p.lock.RUnlock()
154-
return p.recursePin.HasKey(key) ||
155-
p.directPin.HasKey(key) ||
156-
p.isInternalPin(key)
155+
if p.recursePin.HasKey(k) {
156+
return "recursive", true, nil
157+
}
158+
if p.directPin.HasKey(k) {
159+
return "direct", true, nil
160+
}
161+
if p.isInternalPin(k) {
162+
return "internal", true, nil
163+
}
164+
165+
for _, rk := range p.recursePin.GetKeys() {
166+
ss := &searchSet{target: k}
167+
168+
rnd, err := p.dserv.Get(context.Background(), rk)
169+
if err != nil {
170+
return "", false, err
171+
}
172+
173+
err = mdag.EnumerateChildren(context.Background(), p.dserv, rnd, ss)
174+
if err != nil {
175+
return "", false, err
176+
}
177+
178+
if ss.found {
179+
return rk.B58String(), true, nil
180+
}
181+
}
182+
return "", false, nil
157183
}
158184

159185
func (p *pinner) RemovePinWithMode(key key.Key, mode PinMode) {
@@ -309,3 +335,27 @@ func (p *pinner) PinWithMode(k key.Key, mode PinMode) {
309335
p.directPin.AddBlock(k)
310336
}
311337
}
338+
339+
// searchSet implements key.KeySet in
340+
type searchSet struct {
341+
target key.Key
342+
found bool
343+
}
344+
345+
func (ss *searchSet) Add(k key.Key) {
346+
if ss.target == k {
347+
ss.found = true
348+
}
349+
}
350+
351+
func (ss *searchSet) Has(k key.Key) bool {
352+
// returning true to all Has queries will cause EnumerateChildren to return
353+
// almost immediately
354+
return ss.found
355+
}
356+
357+
func (ss *searchSet) Keys() []key.Key {
358+
return nil
359+
}
360+
361+
func (ss *searchSet) Remove(key.Key) {}

‎pin/pin_test.go

+60-18
Original file line numberDiff line numberDiff line change
@@ -2,6 +2,7 @@ package pin
22

33
import (
44
"testing"
5+
"time"
56

67
context "github.com/ipfs/go-ipfs/Godeps/_workspace/src/golang.org/x/net/context"
78

@@ -23,6 +24,17 @@ func randNode() (*mdag.Node, key.Key) {
2324
return nd, k
2425
}
2526

27+
func assertPinned(t *testing.T, p Pinner, k key.Key, failmsg string) {
28+
_, pinned, err := p.IsPinned(k)
29+
if err != nil {
30+
t.Fatal(err)
31+
}
32+
33+
if !pinned {
34+
t.Fatal(failmsg)
35+
}
36+
}
37+
2638
func TestPinnerBasic(t *testing.T) {
2739
ctx := context.Background()
2840

@@ -50,13 +62,11 @@ func TestPinnerBasic(t *testing.T) {
5062
t.Fatal(err)
5163
}
5264

53-
if !p.IsPinned(ak) {
54-
t.Fatal("Failed to find key")
55-
}
65+
assertPinned(t, p, ak, "Failed to find key")
5666

5767
// create new node c, to be indirectly pinned through b
5868
c, _ := randNode()
59-
_, err = dserv.Add(c)
69+
ck, err := dserv.Add(c)
6070
if err != nil {
6171
t.Fatal(err)
6272
}
@@ -84,10 +94,10 @@ func TestPinnerBasic(t *testing.T) {
8494
t.Fatal(err)
8595
}
8696

97+
assertPinned(t, p, ck, "child of recursively pinned node not found")
98+
8799
bk, _ := b.Key()
88-
if !p.IsPinned(bk) {
89-
t.Fatal("Recursively pinned node not found..")
90-
}
100+
assertPinned(t, p, bk, "Recursively pinned node not found..")
91101

92102
d, _ := randNode()
93103
d.AddNodeLink("a", a)
@@ -109,9 +119,7 @@ func TestPinnerBasic(t *testing.T) {
109119
}
110120

111121
dk, _ := d.Key()
112-
if !p.IsPinned(dk) {
113-
t.Fatal("pinned node not found.")
114-
}
122+
assertPinned(t, p, dk, "pinned node not found.")
115123

116124
// Test recursive unpin
117125
err = p.Unpin(ctx, dk, true)
@@ -130,14 +138,10 @@ func TestPinnerBasic(t *testing.T) {
130138
}
131139

132140
// Test directly pinned
133-
if !np.IsPinned(ak) {
134-
t.Fatal("Could not find pinned node!")
135-
}
141+
assertPinned(t, np, ak, "Could not find pinned node!")
136142

137143
// Test recursively pinned
138-
if !np.IsPinned(bk) {
139-
t.Fatal("could not find recursively pinned node")
140-
}
144+
assertPinned(t, np, bk, "could not find recursively pinned node")
141145
}
142146

143147
func TestDuplicateSemantics(t *testing.T) {
@@ -195,7 +199,45 @@ func TestFlush(t *testing.T) {
195199
if err := p.Flush(); err != nil {
196200
t.Fatal(err)
197201
}
198-
if !p.IsPinned(k) {
199-
t.Fatal("expected key to still be pinned")
202+
assertPinned(t, p, k, "expected key to still be pinned")
203+
}
204+
205+
func TestPinRecursiveFail(t *testing.T) {
206+
ctx := context.Background()
207+
dstore := dssync.MutexWrap(ds.NewMapDatastore())
208+
bstore := blockstore.NewBlockstore(dstore)
209+
bserv, err := bs.New(bstore, offline.Exchange(bstore))
210+
if err != nil {
211+
t.Fatal(err)
212+
}
213+
214+
dserv := mdag.NewDAGService(bserv)
215+
216+
p := NewPinner(dstore, dserv)
217+
218+
a, _ := randNode()
219+
b, _ := randNode()
220+
err = a.AddNodeLinkClean("child", b)
221+
if err != nil {
222+
t.Fatal(err)
223+
}
224+
225+
// Note: this isnt a time based test, we expect the pin to fail
226+
mctx, _ := context.WithTimeout(ctx, time.Millisecond)
227+
err = p.Pin(mctx, a, true)
228+
if err == nil {
229+
t.Fatal("should have failed to pin here")
230+
}
231+
232+
_, err = dserv.Add(b)
233+
if err != nil {
234+
t.Fatal(err)
235+
}
236+
237+
// this one is time based... but shouldnt cause any issues
238+
mctx, _ = context.WithTimeout(ctx, time.Second)
239+
err = p.Pin(mctx, a, true)
240+
if err != nil {
241+
t.Fatal(err)
200242
}
201243
}

‎unixfs/mod/dagmodifier_test.go

-15
Original file line numberDiff line numberDiff line change
@@ -10,7 +10,6 @@ import (
1010

1111
"github.com/ipfs/go-ipfs/Godeps/_workspace/src/github.com/jbenet/go-datastore/sync"
1212
"github.com/ipfs/go-ipfs/blocks/blockstore"
13-
key "github.com/ipfs/go-ipfs/blocks/key"
1413
bs "github.com/ipfs/go-ipfs/blockservice"
1514
"github.com/ipfs/go-ipfs/exchange/offline"
1615
imp "github.com/ipfs/go-ipfs/importer"
@@ -564,20 +563,6 @@ func TestCorrectPinning(t *testing.T) {
564563

565564
}
566565

567-
func enumerateChildren(t *testing.T, nd *mdag.Node, ds mdag.DAGService) []key.Key {
568-
var out []key.Key
569-
for _, lnk := range nd.Links {
570-
out = append(out, key.Key(lnk.Hash))
571-
child, err := lnk.GetNode(context.Background(), ds)
572-
if err != nil {
573-
t.Fatal(err)
574-
}
575-
children := enumerateChildren(t, child, ds)
576-
out = append(out, children...)
577-
}
578-
return out
579-
}
580-
581566
func BenchmarkDagmodWrite(b *testing.B) {
582567
b.StopTimer()
583568
dserv, pins := getMockDagServ(b)

0 commit comments

Comments
 (0)
Please sign in to comment.