// Copyright 2020 The Go Authors. All rights reserved.// Use of this source code is governed by a BSD-style// license that can be found in the LICENSE file.package osimport ()var (pollCopyFileRange = poll.CopyFileRangepollSplice = poll.Splice)func ( *File) ( io.Reader) ( int64, bool, error) {// Neither copy_file_range(2) nor splice(2) supports destinations opened with // O_APPEND, so don't bother to try zero-copy with these system calls. // // Visit https://man7.org/linux/man-pages/man2/copy_file_range.2.html#ERRORS and // https://man7.org/linux/man-pages/man2/splice.2.html#ERRORS for details.if .appendMode {return0, false, nil } , , = .copyFileRange()if {return }return .spliceToFile()}func ( *File) ( io.Reader) ( int64, bool, error) {var (int64 *io.LimitedReader )if , , = tryLimitedReader(); <= 0 {return0, true, nil } := getPollFD()// TODO(panjf2000): run some tests to see if we should unlock the non-streams for splice. // Streams benefit the most from the splice(2), non-streams are not even supported in old kernels // where splice(2) will just return EINVAL; newer kernels support non-streams like UDP, but I really // doubt that splice(2) could help non-streams, cuz they usually send small frames respectively // and one splice call would result in one frame. // splice(2) is suitable for large data but the generation of fragments defeats its edge here. // Therefore, don't bother to try splice if the r is not a streaming descriptor.if == nil || !.IsStream {return }varstring , , , = pollSplice(&.pfd, , )if != nil { .N = - }return , , wrapSyscallError(, )}// getPollFD tries to get the poll.FD from the given io.Reader by expecting// the underlying type of r to be the implementation of syscall.Conn that contains// a *net.rawConn.func ( io.Reader) *poll.FD { , := .(syscall.Conn)if ! {returnnil } , := .SyscallConn()if != nil {returnnil } , := .(interface{ () *poll.FD })if ! {returnnil }return .()}func ( *File) ( io.Reader) ( int64, bool, error) {var (int64 *io.LimitedReader )if , , = tryLimitedReader(); <= 0 {return0, true, nil } , := .(*File)if ! {return0, false, nil }if .checkValid("ReadFrom") != nil {// Avoid returning the error as we report handled as false, // leave further error handling as the responsibility of the caller.return0, false, nil } , , = pollCopyFileRange(&.pfd, &.pfd, )if != nil { .N -= }return , , wrapSyscallError("copy_file_range", )}// tryLimitedReader tries to assert the io.Reader to io.LimitedReader, it returns the io.LimitedReader,// the underlying io.Reader and the remaining amount of bytes if the assertion succeeds,// otherwise it just returns the original io.Reader and the theoretical unlimited remaining amount of bytes.func ( io.Reader) (*io.LimitedReader, io.Reader, int64) {varint64 = 1<<63 - 1// by default, copy until EOF , := .(*io.LimitedReader)if ! {returnnil, , } = .Nreturn , .R, }
The pages are generated with Goldsv0.6.7. (GOOS=linux GOARCH=amd64)
Golds is a Go 101 project developed by Tapir Liu.
PR and bug reports are welcome and can be submitted to the issue list.
Please follow @Go100and1 (reachable from the left QR code) to get the latest news of Golds.