From 5bf25690d5dcc6e032555c82905d013c3bf99892 Mon Sep 17 00:00:00 2001 From: Joway Date: Mon, 31 Oct 2022 14:46:25 +0800 Subject: [PATCH] feat: connection flush support write timeout (#206) --- NOTICE | 2 +- connection.go | 6 ++- connection_errors.go | 9 +++-- connection_errors_test.go | 2 +- connection_impl.go | 77 ++++++++++++++++++++++++++++++++++++++- connection_lock.go | 2 +- connection_onevent.go | 3 +- connection_reactor.go | 45 ++++------------------- connection_test.go | 54 ++++++++++++++++++++++++++- fd_operator.go | 2 +- fd_operator_cache.go | 2 +- fd_operator_cache_test.go | 2 +- mux/mux_test.go | 2 +- mux/shard_queue.go | 2 +- mux/shard_queue_test.go | 2 +- net_dialer.go | 2 +- net_dialer_test.go | 2 +- net_listener.go | 2 +- net_listener_test.go | 2 +- net_netfd.go | 2 +- net_netfd_conn.go | 2 +- net_polldesc.go | 2 +- net_polldesc_test.go | 2 +- net_sock.go | 2 +- net_tcpsock.go | 2 +- net_unixsock.go | 2 +- netpoll.go | 2 +- netpoll_options.go | 20 +++++++--- netpoll_server.go | 2 +- netpoll_test.go | 2 +- nocopy.go | 2 +- nocopy_linkbuffer.go | 2 +- nocopy_linkbuffer_race.go | 2 +- nocopy_linkbuffer_test.go | 32 +++++++++++++++- nocopy_readwriter.go | 2 +- nocopy_readwriter_test.go | 2 +- poll.go | 2 +- poll_default_bsd.go | 2 +- poll_default_linux.go | 2 +- poll_loadbalance.go | 2 +- poll_manager.go | 2 +- poll_manager_test.go | 2 +- poll_race_bsd.go | 2 +- poll_race_linux.go | 2 +- poll_test.go | 2 +- sys_epoll_linux.go | 2 +- sys_epoll_linux_arm64.go | 2 +- sys_exec.go | 2 +- sys_exec_test.go | 2 +- sys_keepalive_darwin.go | 2 +- sys_keepalive_openbsd.go | 2 +- sys_keepalive_unix.go | 2 +- sys_sendmsg_bsd.go | 2 +- sys_sendmsg_linux.go | 2 +- sys_sockopt_bsd.go | 2 +- sys_sockopt_linux.go | 2 +- sys_zerocopy_bsd.go | 2 +- sys_zerocopy_linux.go | 2 +- 58 files changed, 244 insertions(+), 102 deletions(-) diff --git a/NOTICE b/NOTICE index cfc8d01b..10de7d47 100644 --- a/NOTICE +++ b/NOTICE @@ -1,5 +1,5 @@ CloudWeGO -Copyright 2021 CloudWeGO authors. +Copyright 2022 CloudWeGO authors. Go Copyright (c) 2009 The Go Authors. \ No newline at end of file diff --git a/connection.go b/connection.go index 62db9d0c..515cbc60 100644 --- a/connection.go +++ b/connection.go @@ -1,4 +1,4 @@ -// Copyright 2021 CloudWeGo Authors +// Copyright 2022 CloudWeGo Authors // // Licensed under the Apache License, Version 2.0 (the "License"); // you may not use this file except in compliance with the License. @@ -45,6 +45,10 @@ type Connection interface { // A zero value for timeout means Reader will not timeout. SetReadTimeout(timeout time.Duration) error + // SetWriteTimeout sets the timeout for future Write calls wait. + // A zero value for timeout means Writer will not timeout. + SetWriteTimeout(timeout time.Duration) error + // SetIdleTimeout sets the idle timeout of connections. // Idle connections that exceed the set timeout are no longer guaranteed to be active, // but can be checked by calling IsActive. diff --git a/connection_errors.go b/connection_errors.go index ced36bd3..b08ba668 100644 --- a/connection_errors.go +++ b/connection_errors.go @@ -1,4 +1,4 @@ -// Copyright 2021 CloudWeGo Authors +// Copyright 2022 CloudWeGo Authors // // Licensed under the Apache License, Version 2.0 (the "License"); // you may not use this file except in compliance with the License. @@ -23,9 +23,9 @@ import ( const ( // The connection closed when in use. ErrConnClosed = syscall.Errno(0x101) - // read I/O buffer timeout, calling by Connection.Reader + // Read I/O buffer timeout, calling by Connection.Reader ErrReadTimeout = syscall.Errno(0x102) - // dial timeout + // Dial timeout ErrDialTimeout = syscall.Errno(0x103) // Calling dialer without timeout. ErrDialNoDeadline = syscall.Errno(0x104) // TODO: no-deadline support in future @@ -33,6 +33,8 @@ const ( ErrUnsupported = syscall.Errno(0x105) // Same as io.EOF ErrEOF = syscall.Errno(0x106) + // Write I/O buffer timeout, calling by Connection.Writer + ErrWriteTimeout = syscall.Errno(0x107) ) const ErrnoMask = 0xFF @@ -94,4 +96,5 @@ var errnos = [...]string{ ErrnoMask & ErrDialNoDeadline: "dial no deadline", ErrnoMask & ErrUnsupported: "netpoll dose not support", ErrnoMask & ErrEOF: "EOF", + ErrnoMask & ErrWriteTimeout: "connection write timeout", } diff --git a/connection_errors_test.go b/connection_errors_test.go index 0788ff77..0d15cb36 100644 --- a/connection_errors_test.go +++ b/connection_errors_test.go @@ -1,4 +1,4 @@ -// Copyright 2021 CloudWeGo Authors +// Copyright 2022 CloudWeGo Authors // // Licensed under the Apache License, Version 2.0 (the "License"); // you may not use this file except in compliance with the License. diff --git a/connection_impl.go b/connection_impl.go index d411726f..58dbf15b 100644 --- a/connection_impl.go +++ b/connection_impl.go @@ -1,4 +1,4 @@ -// Copyright 2021 CloudWeGo Authors +// Copyright 2022 CloudWeGo Authors // // Licensed under the Apache License, Version 2.0 (the "License"); // you may not use this file except in compliance with the License. @@ -38,6 +38,8 @@ type connection struct { readTimer *time.Timer readTrigger chan struct{} waitReadSize int64 + writeTimeout time.Duration + writeTimer *time.Timer writeTrigger chan error inputBuffer *LinkBuffer outputBuffer *LinkBuffer @@ -83,6 +85,14 @@ func (c *connection) SetReadTimeout(timeout time.Duration) error { return nil } +// SetWriteTimeout implements Connection. +func (c *connection) SetWriteTimeout(timeout time.Duration) error { + if timeout >= 0 { + c.writeTimeout = timeout + } + return nil +} + // ------------------------------------------ implement zero-copy reader ------------------------------------------ // Next implements Connection. @@ -474,3 +484,68 @@ func (c *connection) eofError(n int, err error) error { } return err } + +// flush write data directly. +func (c *connection) flush() error { + if c.outputBuffer.IsEmpty() { + return nil + } + // TODO: Let the upper layer pass in whether to use ZeroCopy. + var bs = c.outputBuffer.GetBytes(c.outputBarrier.bs) + var n, err = sendmsg(c.fd, bs, c.outputBarrier.ivs, false && c.supportZeroCopy) + if err != nil && err != syscall.EAGAIN { + return Exception(err, "when flush") + } + if n > 0 { + err = c.outputBuffer.Skip(n) + c.outputBuffer.Release() + if err != nil { + return Exception(err, "when flush") + } + } + // return if write all buffer. + if c.outputBuffer.IsEmpty() { + return nil + } + err = c.operator.Control(PollR2RW) + if err != nil { + return Exception(err, "when flush") + } + + return c.waitFlush() +} + +func (c *connection) waitFlush() (err error) { + if c.writeTimeout == 0 { + select { + case err = <-c.writeTrigger: + } + return err + } + + // set write timeout + if c.writeTimer == nil { + c.writeTimer = time.NewTimer(c.writeTimeout) + } else { + c.writeTimer.Reset(c.writeTimeout) + } + + select { + case err = <-c.writeTrigger: + if !c.writeTimer.Stop() { // clean timer + <-c.writeTimer.C + } + return err + case <-c.writeTimer.C: + select { + // try fetch writeTrigger if both cases fires + case err = <-c.writeTrigger: + return err + default: + } + // if timeout, remove write event from poller + // we cannot flush it again, since we don't if the poller is still process outputBuffer + c.operator.Control(PollRW2R) + return Exception(ErrWriteTimeout, c.remoteAddr.String()) + } +} diff --git a/connection_lock.go b/connection_lock.go index f566ff10..e036de4b 100644 --- a/connection_lock.go +++ b/connection_lock.go @@ -1,4 +1,4 @@ -// Copyright 2021 CloudWeGo Authors +// Copyright 2022 CloudWeGo Authors // // Licensed under the Apache License, Version 2.0 (the "License"); // you may not use this file except in compliance with the License. diff --git a/connection_onevent.go b/connection_onevent.go index 191849b8..a2b8a488 100644 --- a/connection_onevent.go +++ b/connection_onevent.go @@ -1,4 +1,4 @@ -// Copyright 2021 CloudWeGo Authors +// Copyright 2022 CloudWeGo Authors // // Licensed under the Apache License, Version 2.0 (the "License"); // you may not use this file except in compliance with the License. @@ -98,6 +98,7 @@ func (c *connection) onPrepare(opts *options) (err error) { c.SetOnConnect(opts.onConnect) c.SetOnRequest(opts.onRequest) c.SetReadTimeout(opts.readTimeout) + c.SetWriteTimeout(opts.writeTimeout) c.SetIdleTimeout(opts.idleTimeout) // calling prepare first and then register. diff --git a/connection_reactor.go b/connection_reactor.go index dc1b7788..65621b93 100644 --- a/connection_reactor.go +++ b/connection_reactor.go @@ -1,4 +1,4 @@ -// Copyright 2021 CloudWeGo Authors +// Copyright 2022 CloudWeGo Authors // // Licensed under the Apache License, Version 2.0 (the "License"); // you may not use this file except in compliance with the License. @@ -19,7 +19,6 @@ package netpoll import ( "sync/atomic" - "syscall" ) // ------------------------------------------ implement FDOperator ------------------------------------------ @@ -61,13 +60,16 @@ func (c *connection) onClose() error { func (c *connection) closeBuffer() { var onConnect, _ = c.onConnectCallback.Load().(OnConnect) var onRequest, _ = c.onRequestCallback.Load().(OnRequest) + // if client close the connection, we cannot ensure that the poller is not process the buffer, + // so we need to check the buffer length, and if it's an "unclean" close operation, let's give up to reuse the buffer if c.inputBuffer.Len() == 0 || onConnect != nil || onRequest != nil { c.inputBuffer.Close() barrierPool.Put(c.inputBarrier) } - - c.outputBuffer.Close() - barrierPool.Put(c.outputBarrier) + if c.outputBuffer.Len() == 0 || onConnect != nil || onRequest != nil { + c.outputBuffer.Close() + barrierPool.Put(c.outputBarrier) + } } // inputs implements FDOperator. @@ -133,36 +135,3 @@ func (c *connection) rw2r() { c.operator.Control(PollRW2R) c.triggerWrite(nil) } - -// flush write data directly. -func (c *connection) flush() error { - if c.outputBuffer.IsEmpty() { - return nil - } - // TODO: Let the upper layer pass in whether to use ZeroCopy. - var bs = c.outputBuffer.GetBytes(c.outputBarrier.bs) - var n, err = sendmsg(c.fd, bs, c.outputBarrier.ivs, false && c.supportZeroCopy) - if err != nil && err != syscall.EAGAIN { - return Exception(err, "when flush") - } - if n > 0 { - err = c.outputBuffer.Skip(n) - c.outputBuffer.Release() - if err != nil { - return Exception(err, "when flush") - } - } - // return if write all buffer. - if c.outputBuffer.IsEmpty() { - return nil - } - err = c.operator.Control(PollR2RW) - if err != nil { - return Exception(err, "when flush") - } - err = <-c.writeTrigger - if err != nil { - return Exception(err, "when flush") - } - return nil -} diff --git a/connection_test.go b/connection_test.go index 7529d09f..655777c5 100644 --- a/connection_test.go +++ b/connection_test.go @@ -1,4 +1,4 @@ -// Copyright 2021 CloudWeGo Authors +// Copyright 2022 CloudWeGo Authors // // Licensed under the Apache License, Version 2.0 (the "License"); // you may not use this file except in compliance with the License. @@ -260,6 +260,58 @@ func TestLargeBufferWrite(t *testing.T) { wg.Wait() } +func TestWriteTimeout(t *testing.T) { + ln, err := CreateListener("tcp", ":1234") + MustNil(t, err) + + interval := time.Millisecond * 100 + go func() { + for { + conn, err := ln.Accept() + if conn == nil && err == nil { + continue + } + if err != nil { + return + } + go func() { + buf := make([]byte, 1024) + // slow read + for { + _, err := conn.Read(buf) + if err != nil { + err = conn.Close() + MustNil(t, err) + return + } + time.Sleep(interval) + } + }() + } + }() + + conn, err := DialConnection("tcp", ":1234", time.Second) + MustNil(t, err) + + _, err = conn.Writer().Malloc(1024) + MustNil(t, err) + err = conn.Writer().Flush() + MustNil(t, err) + + _ = conn.SetWriteTimeout(time.Millisecond * 10) + _, err = conn.Writer().Malloc(1024 * 1024 * 512) + MustNil(t, err) + err = conn.Writer().Flush() + MustTrue(t, errors.Is(err, ErrWriteTimeout)) + + // close success + err = conn.Close() + MustNil(t, err) + + err = ln.Close() + MustNil(t, err) +} + // TestConnectionLargeMemory is used to verify the memory usage in the large package scenario. func TestConnectionLargeMemory(t *testing.T) { var start, end runtime.MemStats diff --git a/fd_operator.go b/fd_operator.go index 8e025a52..1b59967c 100644 --- a/fd_operator.go +++ b/fd_operator.go @@ -1,4 +1,4 @@ -// Copyright 2021 CloudWeGo Authors +// Copyright 2022 CloudWeGo Authors // // Licensed under the Apache License, Version 2.0 (the "License"); // you may not use this file except in compliance with the License. diff --git a/fd_operator_cache.go b/fd_operator_cache.go index cbdd3391..6e93fa0d 100644 --- a/fd_operator_cache.go +++ b/fd_operator_cache.go @@ -1,4 +1,4 @@ -// Copyright 2021 CloudWeGo Authors +// Copyright 2022 CloudWeGo Authors // // Licensed under the Apache License, Version 2.0 (the "License"); // you may not use this file except in compliance with the License. diff --git a/fd_operator_cache_test.go b/fd_operator_cache_test.go index 96d4924e..3e2838c7 100644 --- a/fd_operator_cache_test.go +++ b/fd_operator_cache_test.go @@ -1,4 +1,4 @@ -// Copyright 2021 CloudWeGo Authors +// Copyright 2022 CloudWeGo Authors // // Licensed under the Apache License, Version 2.0 (the "License"); // you may not use this file except in compliance with the License. diff --git a/mux/mux_test.go b/mux/mux_test.go index b918450c..73c03e09 100644 --- a/mux/mux_test.go +++ b/mux/mux_test.go @@ -1,4 +1,4 @@ -// Copyright 2021 CloudWeGo Authors +// Copyright 2022 CloudWeGo Authors // // Licensed under the Apache License, Version 2.0 (the "License"); // you may not use this file except in compliance with the License. diff --git a/mux/shard_queue.go b/mux/shard_queue.go index 432229ad..d7d6aebb 100644 --- a/mux/shard_queue.go +++ b/mux/shard_queue.go @@ -1,4 +1,4 @@ -// Copyright 2021 CloudWeGo Authors +// Copyright 2022 CloudWeGo Authors // // Licensed under the Apache License, Version 2.0 (the "License"); // you may not use this file except in compliance with the License. diff --git a/mux/shard_queue_test.go b/mux/shard_queue_test.go index acffeb27..3bfae3d4 100644 --- a/mux/shard_queue_test.go +++ b/mux/shard_queue_test.go @@ -1,4 +1,4 @@ -// Copyright 2021 CloudWeGo Authors +// Copyright 2022 CloudWeGo Authors // // Licensed under the Apache License, Version 2.0 (the "License"); // you may not use this file except in compliance with the License. diff --git a/net_dialer.go b/net_dialer.go index 4a2cec66..4c4e8dd2 100644 --- a/net_dialer.go +++ b/net_dialer.go @@ -1,4 +1,4 @@ -// Copyright 2021 CloudWeGo Authors +// Copyright 2022 CloudWeGo Authors // // Licensed under the Apache License, Version 2.0 (the "License"); // you may not use this file except in compliance with the License. diff --git a/net_dialer_test.go b/net_dialer_test.go index 1084de00..3d08ed89 100644 --- a/net_dialer_test.go +++ b/net_dialer_test.go @@ -1,4 +1,4 @@ -// Copyright 2021 CloudWeGo Authors +// Copyright 2022 CloudWeGo Authors // // Licensed under the Apache License, Version 2.0 (the "License"); // you may not use this file except in compliance with the License. diff --git a/net_listener.go b/net_listener.go index 6f90afcb..4bebcac6 100644 --- a/net_listener.go +++ b/net_listener.go @@ -1,4 +1,4 @@ -// Copyright 2021 CloudWeGo Authors +// Copyright 2022 CloudWeGo Authors // // Licensed under the Apache License, Version 2.0 (the "License"); // you may not use this file except in compliance with the License. diff --git a/net_listener_test.go b/net_listener_test.go index 5097035a..315bc9ea 100644 --- a/net_listener_test.go +++ b/net_listener_test.go @@ -1,4 +1,4 @@ -// Copyright 2021 CloudWeGo Authors +// Copyright 2022 CloudWeGo Authors // // Licensed under the Apache License, Version 2.0 (the "License"); // you may not use this file except in compliance with the License. diff --git a/net_netfd.go b/net_netfd.go index b4b6c1cd..0aa09e93 100644 --- a/net_netfd.go +++ b/net_netfd.go @@ -3,7 +3,7 @@ // license that can be found in the LICENSE file. // // This file may have been modified by CloudWeGo authors. (“CloudWeGo Modifications”). -// All CloudWeGo Modifications are Copyright 2021 CloudWeGo authors. +// All CloudWeGo Modifications are Copyright 2022 CloudWeGo authors. //go:build aix || darwin || dragonfly || freebsd || linux || nacl || netbsd || openbsd || solaris // +build aix darwin dragonfly freebsd linux nacl netbsd openbsd solaris diff --git a/net_netfd_conn.go b/net_netfd_conn.go index 27e22d5b..ce174885 100644 --- a/net_netfd_conn.go +++ b/net_netfd_conn.go @@ -1,4 +1,4 @@ -// Copyright 2021 CloudWeGo Authors +// Copyright 2022 CloudWeGo Authors // // Licensed under the Apache License, Version 2.0 (the "License"); // you may not use this file except in compliance with the License. diff --git a/net_polldesc.go b/net_polldesc.go index 7b7415ae..3a5ee32d 100644 --- a/net_polldesc.go +++ b/net_polldesc.go @@ -1,4 +1,4 @@ -// Copyright 2021 CloudWeGo Authors +// Copyright 2022 CloudWeGo Authors // // Licensed under the Apache License, Version 2.0 (the "License"); // you may not use this file except in compliance with the License. diff --git a/net_polldesc_test.go b/net_polldesc_test.go index f2b1fdc2..40804b62 100644 --- a/net_polldesc_test.go +++ b/net_polldesc_test.go @@ -1,4 +1,4 @@ -// Copyright 2021 CloudWeGo Authors +// Copyright 2022 CloudWeGo Authors // // Licensed under the Apache License, Version 2.0 (the "License"); // you may not use this file except in compliance with the License. diff --git a/net_sock.go b/net_sock.go index 94a86738..a3d318c7 100644 --- a/net_sock.go +++ b/net_sock.go @@ -3,7 +3,7 @@ // license that can be found in the LICENSE file. // // This file may have been modified by CloudWeGo authors. (“CloudWeGo Modifications”). -// All CloudWeGo Modifications are Copyright 2021 CloudWeGo authors. +// All CloudWeGo Modifications are Copyright 2022 CloudWeGo authors. //go:build !windows // +build !windows diff --git a/net_tcpsock.go b/net_tcpsock.go index 230ee83c..2c90634b 100644 --- a/net_tcpsock.go +++ b/net_tcpsock.go @@ -3,7 +3,7 @@ // license that can be found in the LICENSE file. // // This file may have been modified by CloudWeGo authors. (“CloudWeGo Modifications”). -// All CloudWeGo Modifications are Copyright 2021 CloudWeGo authors. +// All CloudWeGo Modifications are Copyright 2022 CloudWeGo authors. //go:build !windows // +build !windows diff --git a/net_unixsock.go b/net_unixsock.go index 8a07bfe7..c5213a1c 100644 --- a/net_unixsock.go +++ b/net_unixsock.go @@ -3,7 +3,7 @@ // license that can be found in the LICENSE file. // // This file may have been modified by CloudWeGo authors. (“CloudWeGo Modifications”). -// All CloudWeGo Modifications are Copyright 2021 CloudWeGo authors. +// All CloudWeGo Modifications are Copyright 2022 CloudWeGo authors. //go:build !windows // +build !windows diff --git a/netpoll.go b/netpoll.go index cab46986..7f53f2a2 100644 --- a/netpoll.go +++ b/netpoll.go @@ -1,4 +1,4 @@ -// Copyright 2021 CloudWeGo Authors +// Copyright 2022 CloudWeGo Authors // // Licensed under the Apache License, Version 2.0 (the "License"); // you may not use this file except in compliance with the License. diff --git a/netpoll_options.go b/netpoll_options.go index 1bb3e979..f3ff0453 100644 --- a/netpoll_options.go +++ b/netpoll_options.go @@ -1,4 +1,4 @@ -// Copyright 2021 CloudWeGo Authors +// Copyright 2022 CloudWeGo Authors // // Licensed under the Apache License, Version 2.0 (the "License"); // you may not use this file except in compliance with the License. @@ -72,6 +72,13 @@ func WithReadTimeout(timeout time.Duration) Option { }} } +// WithWriteTimeout sets the write timeout of connections. +func WithWriteTimeout(timeout time.Duration) Option { + return Option{func(op *options) { + op.writeTimeout = timeout + }} +} + // WithIdleTimeout sets the idle timeout of connections. func WithIdleTimeout(timeout time.Duration) Option { return Option{func(op *options) { @@ -85,9 +92,10 @@ type Option struct { } type options struct { - onPrepare OnPrepare - onConnect OnConnect - onRequest OnRequest - readTimeout time.Duration - idleTimeout time.Duration + onPrepare OnPrepare + onConnect OnConnect + onRequest OnRequest + readTimeout time.Duration + writeTimeout time.Duration + idleTimeout time.Duration } diff --git a/netpoll_server.go b/netpoll_server.go index 05cb5994..3a627aff 100644 --- a/netpoll_server.go +++ b/netpoll_server.go @@ -1,4 +1,4 @@ -// Copyright 2021 CloudWeGo Authors +// Copyright 2022 CloudWeGo Authors // // Licensed under the Apache License, Version 2.0 (the "License"); // you may not use this file except in compliance with the License. diff --git a/netpoll_test.go b/netpoll_test.go index 227e1bca..933566aa 100644 --- a/netpoll_test.go +++ b/netpoll_test.go @@ -1,4 +1,4 @@ -// Copyright 2021 CloudWeGo Authors +// Copyright 2022 CloudWeGo Authors // // Licensed under the Apache License, Version 2.0 (the "License"); // you may not use this file except in compliance with the License. diff --git a/nocopy.go b/nocopy.go index 2a31a90e..80df5f9b 100644 --- a/nocopy.go +++ b/nocopy.go @@ -1,4 +1,4 @@ -// Copyright 2021 CloudWeGo Authors +// Copyright 2022 CloudWeGo Authors // // Licensed under the Apache License, Version 2.0 (the "License"); // you may not use this file except in compliance with the License. diff --git a/nocopy_linkbuffer.go b/nocopy_linkbuffer.go index fd861b4c..e148e99f 100644 --- a/nocopy_linkbuffer.go +++ b/nocopy_linkbuffer.go @@ -1,4 +1,4 @@ -// Copyright 2021 CloudWeGo Authors +// Copyright 2022 CloudWeGo Authors // // Licensed under the Apache License, Version 2.0 (the "License"); // you may not use this file except in compliance with the License. diff --git a/nocopy_linkbuffer_race.go b/nocopy_linkbuffer_race.go index b80c6be9..6a471d18 100644 --- a/nocopy_linkbuffer_race.go +++ b/nocopy_linkbuffer_race.go @@ -1,4 +1,4 @@ -// Copyright 2021 CloudWeGo Authors +// Copyright 2022 CloudWeGo Authors // // Licensed under the Apache License, Version 2.0 (the "License"); // you may not use this file except in compliance with the License. diff --git a/nocopy_linkbuffer_test.go b/nocopy_linkbuffer_test.go index 694a8a65..7665edc2 100644 --- a/nocopy_linkbuffer_test.go +++ b/nocopy_linkbuffer_test.go @@ -1,4 +1,4 @@ -// Copyright 2021 CloudWeGo Authors +// Copyright 2022 CloudWeGo Authors // // Licensed under the Apache License, Version 2.0 (the "License"); // you may not use this file except in compliance with the License. @@ -367,6 +367,36 @@ func TestWriteBuffer(t *testing.T) { MustTrue(t, bytes.Equal(buf1.Bytes(), []byte{2, 3})) } +func TestWriteMultiFlush(t *testing.T) { + buf := NewLinkBuffer() + b1, _ := buf.Malloc(4) + b1[0] = 1 + b1[2] = 2 + err := buf.Flush() + MustNil(t, err) + err = buf.Flush() + MustNil(t, err) + MustTrue(t, buf.Bytes()[0] == 1) + MustTrue(t, len(buf.Bytes()) == 4) + + err = buf.Skip(2) + MustNil(t, err) + MustTrue(t, buf.Bytes()[0] == 2) + MustTrue(t, len(buf.Bytes()) == 2) + err = buf.Flush() + MustNil(t, err) + MustTrue(t, buf.Bytes()[0] == 2) + MustTrue(t, len(buf.Bytes()) == 2) + + b2, _ := buf.Malloc(2) + b2[0] = 3 + err = buf.Flush() + MustNil(t, err) + MustTrue(t, buf.Bytes()[0] == 2) + MustTrue(t, buf.Bytes()[2] == 3) + MustTrue(t, len(buf.Bytes()) == 4) +} + func TestWriteBinary(t *testing.T) { // clean & new LinkBufferCap = 8 diff --git a/nocopy_readwriter.go b/nocopy_readwriter.go index f11eb537..2a07c04a 100644 --- a/nocopy_readwriter.go +++ b/nocopy_readwriter.go @@ -1,4 +1,4 @@ -// Copyright 2021 CloudWeGo Authors +// Copyright 2022 CloudWeGo Authors // // Licensed under the Apache License, Version 2.0 (the "License"); // you may not use this file except in compliance with the License. diff --git a/nocopy_readwriter_test.go b/nocopy_readwriter_test.go index 05b26b67..45d6a7ef 100644 --- a/nocopy_readwriter_test.go +++ b/nocopy_readwriter_test.go @@ -1,4 +1,4 @@ -// Copyright 2021 CloudWeGo Authors +// Copyright 2022 CloudWeGo Authors // // Licensed under the Apache License, Version 2.0 (the "License"); // you may not use this file except in compliance with the License. diff --git a/poll.go b/poll.go index a9aac2e9..6e72002c 100644 --- a/poll.go +++ b/poll.go @@ -1,4 +1,4 @@ -// Copyright 2021 CloudWeGo Authors +// Copyright 2022 CloudWeGo Authors // // Licensed under the Apache License, Version 2.0 (the "License"); // you may not use this file except in compliance with the License. diff --git a/poll_default_bsd.go b/poll_default_bsd.go index ec8f070c..af55ee0c 100644 --- a/poll_default_bsd.go +++ b/poll_default_bsd.go @@ -1,4 +1,4 @@ -// Copyright 2021 CloudWeGo Authors +// Copyright 2022 CloudWeGo Authors // // Licensed under the Apache License, Version 2.0 (the "License"); // you may not use this file except in compliance with the License. diff --git a/poll_default_linux.go b/poll_default_linux.go index c31a43a0..09e6009b 100644 --- a/poll_default_linux.go +++ b/poll_default_linux.go @@ -1,4 +1,4 @@ -// Copyright 2021 CloudWeGo Authors +// Copyright 2022 CloudWeGo Authors // // Licensed under the Apache License, Version 2.0 (the "License"); // you may not use this file except in compliance with the License. diff --git a/poll_loadbalance.go b/poll_loadbalance.go index ef597d26..33c3ae54 100644 --- a/poll_loadbalance.go +++ b/poll_loadbalance.go @@ -1,4 +1,4 @@ -// Copyright 2021 CloudWeGo Authors +// Copyright 2022 CloudWeGo Authors // // Licensed under the Apache License, Version 2.0 (the "License"); // you may not use this file except in compliance with the License. diff --git a/poll_manager.go b/poll_manager.go index 398e7a6e..a9f0b0fe 100644 --- a/poll_manager.go +++ b/poll_manager.go @@ -1,4 +1,4 @@ -// Copyright 2021 CloudWeGo Authors +// Copyright 2022 CloudWeGo Authors // // Licensed under the Apache License, Version 2.0 (the "License"); // you may not use this file except in compliance with the License. diff --git a/poll_manager_test.go b/poll_manager_test.go index 7132aa3d..f79f3003 100644 --- a/poll_manager_test.go +++ b/poll_manager_test.go @@ -1,4 +1,4 @@ -// Copyright 2021 CloudWeGo Authors +// Copyright 2022 CloudWeGo Authors // // Licensed under the Apache License, Version 2.0 (the "License"); // you may not use this file except in compliance with the License. diff --git a/poll_race_bsd.go b/poll_race_bsd.go index 39b2d7e6..b53a51b8 100644 --- a/poll_race_bsd.go +++ b/poll_race_bsd.go @@ -1,4 +1,4 @@ -// Copyright 2021 CloudWeGo Authors +// Copyright 2022 CloudWeGo Authors // // Licensed under the Apache License, Version 2.0 (the "License"); // you may not use this file except in compliance with the License. diff --git a/poll_race_linux.go b/poll_race_linux.go index da28cd49..060d7ba3 100644 --- a/poll_race_linux.go +++ b/poll_race_linux.go @@ -1,4 +1,4 @@ -// Copyright 2021 CloudWeGo Authors +// Copyright 2022 CloudWeGo Authors // // Licensed under the Apache License, Version 2.0 (the "License"); // you may not use this file except in compliance with the License. diff --git a/poll_test.go b/poll_test.go index 27a0eb9f..6775b973 100644 --- a/poll_test.go +++ b/poll_test.go @@ -1,4 +1,4 @@ -// Copyright 2021 CloudWeGo Authors +// Copyright 2022 CloudWeGo Authors // // Licensed under the Apache License, Version 2.0 (the "License"); // you may not use this file except in compliance with the License. diff --git a/sys_epoll_linux.go b/sys_epoll_linux.go index d073345c..2c02f38d 100644 --- a/sys_epoll_linux.go +++ b/sys_epoll_linux.go @@ -1,4 +1,4 @@ -// Copyright 2021 CloudWeGo Authors +// Copyright 2022 CloudWeGo Authors // // Licensed under the Apache License, Version 2.0 (the "License"); // you may not use this file except in compliance with the License. diff --git a/sys_epoll_linux_arm64.go b/sys_epoll_linux_arm64.go index 9d33ad16..c83781b5 100644 --- a/sys_epoll_linux_arm64.go +++ b/sys_epoll_linux_arm64.go @@ -1,4 +1,4 @@ -// Copyright 2021 CloudWeGo Authors +// Copyright 2022 CloudWeGo Authors // // Licensed under the Apache License, Version 2.0 (the "License"); // you may not use this file except in compliance with the License. diff --git a/sys_exec.go b/sys_exec.go index 3558be14..cf3472e0 100644 --- a/sys_exec.go +++ b/sys_exec.go @@ -1,4 +1,4 @@ -// Copyright 2021 CloudWeGo Authors +// Copyright 2022 CloudWeGo Authors // // Licensed under the Apache License, Version 2.0 (the "License"); // you may not use this file except in compliance with the License. diff --git a/sys_exec_test.go b/sys_exec_test.go index 86e4002f..54398df1 100644 --- a/sys_exec_test.go +++ b/sys_exec_test.go @@ -1,4 +1,4 @@ -// Copyright 2021 CloudWeGo Authors +// Copyright 2022 CloudWeGo Authors // // Licensed under the Apache License, Version 2.0 (the "License"); // you may not use this file except in compliance with the License. diff --git a/sys_keepalive_darwin.go b/sys_keepalive_darwin.go index b61f368f..30e602df 100644 --- a/sys_keepalive_darwin.go +++ b/sys_keepalive_darwin.go @@ -1,4 +1,4 @@ -// Copyright 2021 CloudWeGo Authors +// Copyright 2022 CloudWeGo Authors // // Licensed under the Apache License, Version 2.0 (the "License"); // you may not use this file except in compliance with the License. diff --git a/sys_keepalive_openbsd.go b/sys_keepalive_openbsd.go index e58d9b4f..a67bcdcb 100644 --- a/sys_keepalive_openbsd.go +++ b/sys_keepalive_openbsd.go @@ -1,4 +1,4 @@ -// Copyright 2021 CloudWeGo Authors +// Copyright 2022 CloudWeGo Authors // // Licensed under the Apache License, Version 2.0 (the "License"); // you may not use this file except in compliance with the License. diff --git a/sys_keepalive_unix.go b/sys_keepalive_unix.go index 2bf8e388..56459edf 100644 --- a/sys_keepalive_unix.go +++ b/sys_keepalive_unix.go @@ -1,4 +1,4 @@ -// Copyright 2021 CloudWeGo Authors +// Copyright 2022 CloudWeGo Authors // // Licensed under the Apache License, Version 2.0 (the "License"); // you may not use this file except in compliance with the License. diff --git a/sys_sendmsg_bsd.go b/sys_sendmsg_bsd.go index 2d9a3b57..b808a5d2 100644 --- a/sys_sendmsg_bsd.go +++ b/sys_sendmsg_bsd.go @@ -1,4 +1,4 @@ -// Copyright 2021 CloudWeGo Authors +// Copyright 2022 CloudWeGo Authors // // Licensed under the Apache License, Version 2.0 (the "License"); // you may not use this file except in compliance with the License. diff --git a/sys_sendmsg_linux.go b/sys_sendmsg_linux.go index 5a849db2..a5a63c58 100644 --- a/sys_sendmsg_linux.go +++ b/sys_sendmsg_linux.go @@ -1,4 +1,4 @@ -// Copyright 2021 CloudWeGo Authors +// Copyright 2022 CloudWeGo Authors // // Licensed under the Apache License, Version 2.0 (the "License"); // you may not use this file except in compliance with the License. diff --git a/sys_sockopt_bsd.go b/sys_sockopt_bsd.go index 586892ae..10e7b99d 100644 --- a/sys_sockopt_bsd.go +++ b/sys_sockopt_bsd.go @@ -3,7 +3,7 @@ // license that can be found in the LICENSE file. // // This file may have been modified by CloudWeGo authors. (“CloudWeGo Modifications”). -// All CloudWeGo Modifications are Copyright 2021 CloudWeGo authors. +// All CloudWeGo Modifications are Copyright 2022 CloudWeGo authors. //go:build darwin || dragonfly || freebsd || netbsd || openbsd // +build darwin dragonfly freebsd netbsd openbsd diff --git a/sys_sockopt_linux.go b/sys_sockopt_linux.go index 5a7dddce..18860946 100644 --- a/sys_sockopt_linux.go +++ b/sys_sockopt_linux.go @@ -3,7 +3,7 @@ // license that can be found in the LICENSE file. // // This file may have been modified by CloudWeGo authors. (“CloudWeGo Modifications”). -// All CloudWeGo Modifications are Copyright 2021 CloudWeGo authors. +// All CloudWeGo Modifications are Copyright 2022 CloudWeGo authors. package netpoll diff --git a/sys_zerocopy_bsd.go b/sys_zerocopy_bsd.go index 7f889b0f..387f9601 100644 --- a/sys_zerocopy_bsd.go +++ b/sys_zerocopy_bsd.go @@ -1,4 +1,4 @@ -// Copyright 2021 CloudWeGo Authors +// Copyright 2022 CloudWeGo Authors // // Licensed under the Apache License, Version 2.0 (the "License"); // you may not use this file except in compliance with the License. diff --git a/sys_zerocopy_linux.go b/sys_zerocopy_linux.go index 4d463967..0d38a386 100644 --- a/sys_zerocopy_linux.go +++ b/sys_zerocopy_linux.go @@ -1,4 +1,4 @@ -// Copyright 2021 CloudWeGo Authors +// Copyright 2022 CloudWeGo Authors // // Licensed under the Apache License, Version 2.0 (the "License"); // you may not use this file except in compliance with the License.