@@ -63,16 +63,13 @@ func NewPBFileReader(ctx context.Context, n *mdag.ProtoNode, file *ft.FSNode, se
63
63
64
64
const preloadSize = 10
65
65
66
- func (dr * PBDagReader ) preloadNextNodes (ctx context.Context ) {
67
- beg := dr .linkPosition
66
+ func (dr * PBDagReader ) preload (ctx context.Context , beg int ) {
68
67
end := beg + preloadSize
69
68
if end >= len (dr .links ) {
70
69
end = len (dr .links )
71
70
}
72
71
73
- for i , p := range ipld .GetNodes (ctx , dr .serv , dr .links [beg :end ]) {
74
- dr .promises [beg + i ] = p
75
- }
72
+ copy (dr .promises [beg :], ipld .GetNodes (ctx , dr .serv , dr .links [beg :end ]))
76
73
}
77
74
78
75
// precalcNextBuf follows the next link in line and loads it from the
@@ -87,15 +84,42 @@ func (dr *PBDagReader) precalcNextBuf(ctx context.Context) error {
87
84
return io .EOF
88
85
}
89
86
90
- if dr .promises [dr .linkPosition ] == nil {
91
- dr .preloadNextNodes (ctx )
87
+ // If we drop to <= preloadSize/2 preloading nodes, preload the next 10.
88
+ for i := dr .linkPosition ; i < dr .linkPosition + preloadSize / 2 && i < len (dr .promises ); i ++ {
89
+ // TODO: check if canceled.
90
+ if dr .promises [i ] == nil {
91
+ dr .preload (ctx , i )
92
+ break
93
+ }
92
94
}
93
95
94
96
nxt , err := dr .promises [dr .linkPosition ].Get (ctx )
95
- if err != nil {
97
+ dr .promises [dr .linkPosition ] = nil
98
+ switch err {
99
+ case nil :
100
+ case context .DeadlineExceeded , context .Canceled :
101
+ err = ctx .Err ()
102
+ if err != nil {
103
+ return ctx .Err ()
104
+ }
105
+ // In this case, the context used to *preload* the node has been canceled.
106
+ // We need to retry the load with our context and we might as
107
+ // well preload some extra nodes while we're at it.
108
+ //
109
+ // Note: When using `Read`, this code will never execute as
110
+ // `Read` will use the global context. It only runs if the user
111
+ // explicitly reads with a custom context (e.g., by calling
112
+ // `CtxReadFull`).
113
+ dr .preload (ctx , dr .linkPosition )
114
+ nxt , err = dr .promises [dr .linkPosition ].Get (ctx )
115
+ dr .promises [dr .linkPosition ] = nil
116
+ if err != nil {
117
+ return err
118
+ }
119
+ default :
96
120
return err
97
121
}
98
- dr . promises [ dr . linkPosition ] = nil
122
+
99
123
dr .linkPosition ++
100
124
101
125
switch nxt := nxt .(type ) {
0 commit comments