addressing comments from CR
License: MIT Signed-off-by: Jeromy <jeromyj@gmail.com>
Jeromy committed
Jul 10, 2015 at 10:49 UTC
16c4d8cdcbfd3aaad06580d223aa2da503f6933d
4 files changed
+115
-39
pin/gc/gc.go
+1
-1
@@ -100,7 +100,7 @@ func ColoredSet(pn pin.Pinner, ds dag.DAGService) (key.KeySet, error) {
100
gcs.Add(k)
101
}
102
103
- err = Color(ds, gcs, pn.InternalPins())
103
+ err = Descendants(ds, gcs, pn.InternalPins())
104
if err != nil {
105
return nil, err
106
}
pin/pin.go
+55
-5
@@ -35,7 +35,7 @@ const (
35
)
36
37
type Pinner interface {
38
- IsPinned(key.Key) bool
38
+ IsPinned(key.Key) (string, bool, error)
39
Pin(context.Context, *mdag.Node, bool) error
40
Unpin(context.Context, key.Key, bool) error
41
@@ -147,12 +147,38 @@ func (p *pinner) isInternalPin(key key.Key) bool {
147
}
148
149
// IsPinned returns whether or not the given key is pinned
150
-func (p *pinner) IsPinned(key key.Key) bool {
150
+// and an explanation of why its pinned
151
+func (p *pinner) IsPinned(k key.Key) (string, bool, error) {
152
p.lock.RLock()
153
defer p.lock.RUnlock()
153
- return p.recursePin.HasKey(key) ||
154
- p.directPin.HasKey(key) ||
155
- p.isInternalPin(key)
154
+ if p.recursePin.HasKey(k) {
155
+ return "recursive", true, nil
156
+ }
157
+ if p.directPin.HasKey(k) {
158
+ return "direct", true, nil
159
+ }
160
+ if p.isInternalPin(k) {
161
+ return "internal", true, nil
162
+ }
163
+
164
+ for _, rk := range p.recursePin.GetKeys() {
165
+ ss := &searchSet{target: k}
166
+
167
+ rnd, err := p.dserv.Get(context.Background(), rk)
168
+ if err != nil {
169
+ return "", false, err
170
+ }
171
+
172
+ err = mdag.EnumerateChildren(context.Background(), p.dserv, rnd, ss)
173
+ if err != nil {
174
+ return "", false, err
175
+ }
176
+
177
+ if ss.found {
178
+ return rk.B58String(), true, nil
179
+ }
180
+ }
181
+ return "", false, nil
182
}
183
184
func (p *pinner) RemovePinWithMode(key key.Key, mode PinMode) {
@@ -308,3 +334,27 @@ func (p *pinner) PinWithMode(k key.Key, mode PinMode) {
334
p.directPin.AddBlock(k)
335
}
336
}
337
+
338
+// searchSet implements key.KeySet in
339
+type searchSet struct {
340
+ target key.Key
341
+ found bool
342
+}
343
+
344
+func (ss *searchSet) Add(k key.Key) {
345
+ if ss.target == k {
346
+ ss.found = true
347
+ }
348
+}
349
+
350
+func (ss *searchSet) Has(k key.Key) bool {
351
+ // returning true to all Has queries will cause EnumerateChildren to return
352
+ // almost immediately
353
+ return ss.found
354
+}
355
+
356
+func (ss *searchSet) Keys() []key.Key {
357
+ return nil
358
+}
359
+
360
+func (ss *searchSet) Remove(key.Key) {}
pin/pin_test.go
+59
-18
@@ -24,6 +24,17 @@ func randNode() (*mdag.Node, key.Key) {
24
return nd, k
25
}
26
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
+
38
func TestPinnerBasic(t *testing.T) {
39
ctx := context.Background()
40
@@ -48,13 +59,11 @@ func TestPinnerBasic(t *testing.T) {
59
t.Fatal(err)
60
}
61
51
- if !p.IsPinned(ak) {
52
- t.Fatal("Failed to find key")
53
- }
62
+ assertPinned(t, p, ak, "Failed to find key")
63
64
// create new node c, to be indirectly pinned through b
65
c, _ := randNode()
57
- _, err = dserv.Add(c)
66
+ ck, err := dserv.Add(c)
67
if err != nil {
68
t.Fatal(err)
69
}
@@ -82,10 +91,10 @@ func TestPinnerBasic(t *testing.T) {
91
t.Fatal(err)
92
}
93
94
+ assertPinned(t, p, ck, "child of recursively pinned node not found")
95
+
96
bk, _ := b.Key()
86
- if !p.IsPinned(bk) {
87
- t.Fatal("Recursively pinned node not found..")
88
- }
97
+ assertPinned(t, p, bk, "Recursively pinned node not found..")
98
99
d, _ := randNode()
100
d.AddNodeLink("a", a)
@@ -107,9 +116,7 @@ func TestPinnerBasic(t *testing.T) {
116
}
117
118
dk, _ := d.Key()
110
- if !p.IsPinned(dk) {
111
- t.Fatal("pinned node not found.")
112
- }
119
+ assertPinned(t, p, dk, "pinned node not found.")
120
121
// Test recursive unpin
122
err = p.Unpin(ctx, dk, true)
@@ -128,14 +135,10 @@ func TestPinnerBasic(t *testing.T) {
135
}
136
137
// Test directly pinned
131
- if !np.IsPinned(ak) {
132
- t.Fatal("Could not find pinned node!")
133
- }
138
+ assertPinned(t, np, ak, "Could not find pinned node!")
139
140
// Test recursively pinned
136
- if !np.IsPinned(bk) {
137
- t.Fatal("could not find recursively pinned node")
138
- }
141
+ assertPinned(t, np, bk, "could not find recursively pinned node")
142
}
143
144
func TestDuplicateSemantics(t *testing.T) {
@@ -187,8 +190,46 @@ func TestFlush(t *testing.T) {
190
if err := p.Flush(); err != nil {
191
t.Fatal(err)
192
}
190
- if !p.IsPinned(k) {
191
- t.Fatal("expected key to still be pinned")
193
+ assertPinned(t, p, k, "expected key to still be pinned")
194
+}
195
+
196
+func TestPinRecursiveFail(t *testing.T) {
197
+ ctx := context.Background()
198
+ dstore := dssync.MutexWrap(ds.NewMapDatastore())
199
+ bstore := blockstore.NewBlockstore(dstore)
200
+ bserv, err := bs.New(bstore, offline.Exchange(bstore))
201
+ if err != nil {
202
+ t.Fatal(err)
203
+ }
204
+
205
+ dserv := mdag.NewDAGService(bserv)
206
+
207
+ p := NewPinner(dstore, dserv)
208
+
209
+ a, _ := randNode()
210
+ b, _ := randNode()
211
+ err = a.AddNodeLinkClean("child", b)
212
+ if err != nil {
213
+ t.Fatal(err)
214
+ }
215
+
216
+ // Note: this isnt a time based test, we expect the pin to fail
217
+ mctx, _ := context.WithTimeout(ctx, time.Millisecond)
218
+ err = p.Pin(mctx, a, true)
219
+ if err == nil {
220
+ t.Fatal("should have failed to pin here")
221
+ }
222
+
223
+ _, err = dserv.Add(b)
224
+ if err != nil {
225
+ t.Fatal(err)
226
+ }
227
+
228
+ // this one is time based... but shouldnt cause any issues
229
+ mctx, _ = context.WithTimeout(ctx, time.Second)
230
+ err = p.Pin(mctx, a, true)
231
+ if err != nil {
232
+ t.Fatal(err)
233
}
234
}
235
unixfs/mod/dagmodifier_test.go
-15
@@ -10,7 +10,6 @@ import (
10
11
"github.com/ipfs/go-ipfs/Godeps/_workspace/src/github.com/jbenet/go-datastore/sync"
12
"github.com/ipfs/go-ipfs/blocks/blockstore"
13
- key "github.com/ipfs/go-ipfs/blocks/key"
13
bs "github.com/ipfs/go-ipfs/blockservice"
14
"github.com/ipfs/go-ipfs/exchange/offline"
15
imp "github.com/ipfs/go-ipfs/importer"
@@ -564,20 +563,6 @@ func TestCorrectPinning(t *testing.T) {
563
564
}
565
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
-
566
func BenchmarkDagmodWrite(b *testing.B) {
567
b.StopTimer()
568
dserv, pins := getMockDagServ(b)