Readdir implements the Directory interface.
(ctx context.Context, n int)
| 143 | |
| 144 | // Readdir implements the Directory interface. |
| 145 | func (dr *DirReader) Readdir(ctx context.Context, n int) (entries []DirectoryEntry, err error) { |
| 146 | sts, err := dr.StaticSet(ctx) |
| 147 | if err != nil { |
| 148 | return nil, fmt.Errorf("schema/dirreader: can't get StaticSet: %v", err) |
| 149 | } |
| 150 | up := dr.current + n |
| 151 | if n <= 0 { |
| 152 | dr.current = 0 |
| 153 | up = len(sts) |
| 154 | } else { |
| 155 | if n > (len(sts) - dr.current) { |
| 156 | up = len(sts) |
| 157 | } |
| 158 | } |
| 159 | |
| 160 | // TODO(bradfitz): push down information to the fetcher |
| 161 | // (e.g. cachingfetcher -> remote client http) that we're |
| 162 | // going to load a bunch, so the HTTP client (if not using |
| 163 | // SPDY) can do discovery and see if the server supports a |
| 164 | // batch handler, then get them all in one round-trip, rather |
| 165 | // than attacking the server with hundreds of parallel TLS |
| 166 | // setups. |
| 167 | |
| 168 | type res struct { |
| 169 | ent DirectoryEntry |
| 170 | err error |
| 171 | } |
| 172 | var cs []chan res |
| 173 | |
| 174 | // Kick off all directory entry loads. |
| 175 | gate := syncutil.NewGate(20) // Limit IO concurrency |
| 176 | for _, entRef := range sts[dr.current:up] { |
| 177 | c := make(chan res, 1) |
| 178 | cs = append(cs, c) |
| 179 | gate.Start() |
| 180 | go func(entRef blob.Ref) { |
| 181 | defer gate.Done() |
| 182 | entry, err := NewDirectoryEntryFromBlobRef(ctx, dr.fetcher, entRef) |
| 183 | c <- res{entry, err} |
| 184 | }(entRef) |
| 185 | } |
| 186 | |
| 187 | for _, c := range cs { |
| 188 | res := <-c |
| 189 | if res.err != nil { |
| 190 | return nil, fmt.Errorf("schema/dirreader: can't create dirEntry: %v", res.err) |
| 191 | } |
| 192 | entries = append(entries, res.ent) |
| 193 | } |
| 194 | return entries, nil |
| 195 | } |
no test coverage detected