Repository: syncthing/syncthing
File: lib/model/folder_sendrecv.go (Go)

Code before:
			return
		default:
		}

		// Select the least busy device to pull the block from. If we found no
		// feasible device at all, fail the block (and in the long run, the
		// file).
		selected, found := activity.leastBusy(candidates)
		if !found {
			if lastError != nil {
				state.fail(errors.Wrap(lastError, "pull"))
			} else {
				state.fail(errors.Wrap(errNoDevice, "pull"))
			}
			break
		}

		candidates = removeAvailability(candidates, selected)

		// Fetch the block, while marking the selected device as in use so that
		// leastBusy can select another device when someone else asks.
		activity.using(selected)
		var buf []byte
		done := make(chan struct{})
		go func() {
			buf, lastError = f.model.requestGlobal(selected.ID, f.folderID, state.file.Name, state.block.Offset, int(state.block.Size), state.block.Hash, state.block.WeakHash, selected.FromTemporary)
			close(done)
		}()
		select {
		case <-done:
		case <-f.ctx.Done():
			state.fail(errors.Wrap(f.ctx.Err(), "folder stopped"))
			return
		}
		activity.done(selected)
		if lastError != nil {
			l.Debugln("request:", f.folderID, state.file.Name, state.block.Offset, state.block.Size, "returned error:", lastError)
			continue
		}

		// Verify that the received block matches the desired hash, if not
		// try pulling it from another device.
		lastError = verifyBuffer(buf, state.block)
		if lastError != nil {
			l.Debugln("request:", f.folderID, state.file.Name, state.block.Offset, state.block.Size, "hash mismatch")
			continue
		}

		// Save the block data we got from the cluster
		_, err = fd.WriteAt(buf, state.block.Offset)
		if err != nil {

Review comment (suggestion):
Push the context down?

You could even push it down part of asyncMessage which does not dispatch it if the context is closed, and the response channel.

Code after:
			break
		default:
		}

		// Select the least busy device to pull the block from. If we found no
		// feasible device at all, fail the block (and in the long run, the
		// file).
		selected, found := activity.leastBusy(candidates)
		if !found {
			if lastError != nil {
				state.fail(errors.Wrap(lastError, "pull"))
			} else {
				state.fail(errors.Wrap(errNoDevice, "pull"))
			}
			break
		}

		candidates = removeAvailability(candidates, selected)

		// Fetch the block, while marking the selected device as in use so that
		// leastBusy can select another device when someone else asks.
		activity.using(selected)
		var buf []byte
		buf, lastError = f.model.requestGlobal(f.ctx, selected.ID, f.folderID, state.file.Name, state.block.Offset, int(state.block.Size), state.block.Hash, state.block.WeakHash, selected.FromTemporary)
		activity.done(selected)
		if lastError != nil {
			l.Debugln("request:", f.folderID, state.file.Name, state.block.Offset, state.block.Size, "returned error:", lastError)
			continue
		}

		// Verify that the received block matches the desired hash, if not
		// try pulling it from another device.
		lastError = verifyBuffer(buf, state.block)
		if lastError != nil {
			l.Debugln("request:", f.folderID, state.file.Name, state.block.Offset, state.block.Size, "hash mismatch")
			continue
		}

		// Save the block data we got from the cluster
		_, err = fd.WriteAt(buf, state.block.Offset)
		if err != nil {
			state.fail(errors.Wrap(err, "save"))
		} else {
			state.pullDone(state.block)
		}
		break
	}
	out <- state.sharedPullerState
}

func (f *sendReceiveFolder) performFinish(file, curFile protocol.FileInfo, hasCurFile bool, tempName string, dbUpdateChan chan<- dbUpdateJob, scanChan chan<- string) error {