(ctx context.Context, bs blobserver.StatReceiver, file *Builder, r io.Reader)
| 289 | } |
| 290 | |
| 291 | func writeFileChunks(ctx context.Context, bs blobserver.StatReceiver, file *Builder, r io.Reader) (n int64, spans []span, outerr error) { |
| 292 | src := ¬eEOFReader{r: r} |
| 293 | bufr := bufio.NewReaderSize(src, bufioReaderSize) |
| 294 | spans = []span{} // the tree of spans, cut on interesting rollsum boundaries |
| 295 | rs := rollsum.New() |
| 296 | var last int64 |
| 297 | var buf bytes.Buffer |
| 298 | blobSize := 0 // of the next blob being built, should be same as buf.Len() |
| 299 | |
| 300 | const chunksInFlight = 32 // at ~64 KB chunks, this is ~2MB memory per file |
| 301 | gatec := syncutil.NewGate(chunksInFlight) |
| 302 | firsterrc := make(chan error, 1) |
| 303 | |
| 304 | // uploadLastSpan runs in the same goroutine as the loop below and is responsible for |
| 305 | // starting uploading the contents of the buf. It returns false if there's been |
| 306 | // an error and the loop below should be stopped. |
| 307 | uploadLastSpan := func() bool { |
| 308 | chunk := buf.String() |
| 309 | buf.Reset() |
| 310 | br := blob.RefFromString(chunk) |
| 311 | spans[len(spans)-1].br = br |
| 312 | select { |
| 313 | case outerr = <-firsterrc: |
| 314 | return false |
| 315 | default: |
| 316 | // No error seen so far, continue. |
| 317 | } |
| 318 | gatec.Start() |
| 319 | go func() { |
| 320 | defer gatec.Done() |
| 321 | if _, err := uploadString(ctx, bs, br, chunk); err != nil { |
| 322 | select { |
| 323 | case firsterrc <- err: |
| 324 | default: |
| 325 | } |
| 326 | } |
| 327 | }() |
| 328 | return true |
| 329 | } |
| 330 | |
| 331 | for { |
| 332 | c, err := bufr.ReadByte() |
| 333 | if err == io.EOF { |
| 334 | if n != last { |
| 335 | spans = append(spans, span{from: last, to: n}) |
| 336 | if !uploadLastSpan() { |
| 337 | return |
| 338 | } |
| 339 | } |
| 340 | break |
| 341 | } |
| 342 | if err != nil { |
| 343 | return 0, nil, err |
| 344 | } |
| 345 | |
| 346 | buf.WriteByte(c) |
| 347 | n++ |
| 348 | blobSize++ |
no test coverage detected