...
Run Format

Source file src/net/sendfile_linux.go

     1	// Copyright 2011 The Go Authors. All rights reserved.
     2	// Use of this source code is governed by a BSD-style
     3	// license that can be found in the LICENSE file.
     4	
     5	package net
     6	
     7	import (
     8		"io"
     9		"os"
    10		"syscall"
    11	)
    12	
    13	// maxSendfileSize is the largest chunk size we ask the kernel to copy
    14	// at a time.
    15	const maxSendfileSize int = 4 << 20
    16	
    17	// sendFile copies the contents of r to c using the sendfile
    18	// system call to minimize copies.
    19	//
    20	// if handled == true, sendFile returns the number of bytes copied and any
    21	// non-EOF error.
    22	//
    23	// if handled == false, sendFile performed no work.
    24	func sendFile(c *netFD, r io.Reader) (written int64, err error, handled bool) {
    25		var remain int64 = 1 << 62 // by default, copy until EOF
    26	
    27		lr, ok := r.(*io.LimitedReader)
    28		if ok {
    29			remain, r = lr.N, lr.R
    30			if remain <= 0 {
    31				return 0, nil, true
    32			}
    33		}
    34		f, ok := r.(*os.File)
    35		if !ok {
    36			return 0, nil, false
    37		}
    38	
    39		if err := c.writeLock(); err != nil {
    40			return 0, err, true
    41		}
    42		defer c.writeUnlock()
    43	
    44		dst := c.sysfd
    45		src := int(f.Fd())
    46		for remain > 0 {
    47			n := maxSendfileSize
    48			if int64(n) > remain {
    49				n = int(remain)
    50			}
    51			n, err1 := syscall.Sendfile(dst, src, nil, n)
    52			if n > 0 {
    53				written += int64(n)
    54				remain -= int64(n)
    55			}
    56			if n == 0 && err1 == nil {
    57				break
    58			}
    59			if err1 == syscall.EAGAIN {
    60				if err1 = c.pd.waitWrite(); err1 == nil {
    61					continue
    62				}
    63			}
    64			if err1 != nil {
    65				// This includes syscall.ENOSYS (no kernel
    66				// support) and syscall.EINVAL (fd types which
    67				// don't implement sendfile)
    68				err = err1
    69				break
    70			}
    71		}
    72		if lr != nil {
    73			lr.N = remain
    74		}
    75		if err != nil {
    76			err = os.NewSyscallError("sendfile", err)
    77		}
    78		return written, err, written > 0
    79	}
    80	

View as plain text