MCPcopy
hub / github.com/syncthing/syncthing / pullBlock

Method pullBlock

lib/model/folder_sendrecv.go:1564–1656  ·  view source on GitHub ↗
(ctx context.Context, state pullBlockState, out chan<- *sharedPullerState)

Source from the content-addressed store, hash-verified

1562}
1563
1564func (f *sendReceiveFolder) pullBlock(ctx context.Context, state pullBlockState, out chan<- *sharedPullerState) {
1565 // Get an fd to the temporary file. Technically we don't need it until
1566 // after fetching the block, but if we run into an error here there is
1567 // no point in issuing the request to the network.
1568 fd, err := state.tempFile()
1569 if err != nil {
1570 out <- state.sharedPullerState
1571 return
1572 }
1573
1574 if state.block.IsEmpty() {
1575 // There is no need to request a block of all zeroes. Pretend we
1576 // requested it and handled it correctly.
1577 if state.reused != 0 || f.DisableSparseFiles {
1578 // We are reusing a file (contents apparently weren't all-zeroes
1579 // previously), or sparse files are disabled, so we need to
1580 // actually write the block.
1581 zeroes := make([]byte, state.block.Size)
1582 err = f.limitedWriteAt(ctx, fd, zeroes, state.block.Offset)
1583 }
1584 if err != nil {
1585 state.fail(fmt.Errorf("save: %w", err))
1586 } else {
1587 state.pullDone(state.block)
1588 }
1589 out <- state.sharedPullerState
1590 return
1591 }
1592
1593 var lastError error
1594 candidates := f.model.blockAvailability(f.FolderConfiguration, state.file, state.block)
1595loop:
1596 for {
1597 select {
1598 case <-ctx.Done():
1599 state.fail(fmt.Errorf("folder stopped: %w", ctx.Err()))
1600 break loop
1601 default:
1602 }
1603
1604 // Select the least busy device to pull the block from. If we found no
1605 // feasible device at all, fail the block (and in the long run, the
1606 // file).
1607 found := activity.leastBusy(candidates)
1608 if found == -1 {
1609 if lastError != nil {
1610 state.fail(fmt.Errorf("pull: %w", lastError))
1611 } else {
1612 state.fail(fmt.Errorf("pull: %w", errNoDevice))
1613 }
1614 break
1615 }
1616
1617 selected := candidates[found]
1618 candidates[found] = candidates[len(candidates)-1]
1619 candidates = candidates[:len(candidates)-1]
1620
1621 // Fetch the block, while marking the selected device as in use so that

Callers 2

pullerRoutineMethod · 0.95
TestPullEmptyBlockFunction · 0.80

Calls 15

limitedWriteAtMethod · 0.95
verifyBufferMethod · 0.95
FilePathFunction · 0.92
ErrorFunction · 0.92
tempFileMethod · 0.80
failMethod · 0.80
pullDoneMethod · 0.80
blockAvailabilityMethod · 0.80
DoneMethod · 0.80
leastBusyMethod · 0.80
usingMethod · 0.80
ShortMethod · 0.80

Tested by 1

TestPullEmptyBlockFunction · 0.64