github.com/cloudwego/kitex@v0.9.0/pkg/remote/trans/netpoll/bytebuf.go (about) 1 /* 2 * Copyright 2021 CloudWeGo Authors 3 * 4 * Licensed under the Apache License, Version 2.0 (the "License"); 5 * you may not use this file except in compliance with the License. 6 * You may obtain a copy of the License at 7 * 8 * http://www.apache.org/licenses/LICENSE-2.0 9 * 10 * Unless required by applicable law or agreed to in writing, software 11 * distributed under the License is distributed on an "AS IS" BASIS, 12 * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. 13 * See the License for the specific language governing permissions and 14 * limitations under the License. 15 */ 16 17 package netpoll 18 19 import ( 20 "errors" 21 "io" 22 "sync" 23 24 "github.com/cloudwego/netpoll" 25 26 "github.com/cloudwego/kitex/pkg/remote" 27 ) 28 29 var bytebufPool sync.Pool 30 31 func init() { 32 bytebufPool.New = newNetpollByteBuffer 33 } 34 35 // NewReaderByteBuffer creates a new remote.ByteBuffer using the given netpoll.ZeroCopyReader. 36 func NewReaderByteBuffer(r netpoll.Reader) remote.ByteBuffer { 37 bytebuf := bytebufPool.Get().(*netpollByteBuffer) 38 bytebuf.reader = r 39 // TODO(wangtieju): fix me when netpoll support netpoll.Reader 40 // and LinkBuffer not support io.Reader, type assertion would fail when r is from NewBuffer 41 if ir, ok := r.(io.Reader); ok { 42 bytebuf.ioReader = ir 43 } 44 bytebuf.status = remote.BitReadable 45 bytebuf.readSize = 0 46 return bytebuf 47 } 48 49 // NewWriterByteBuffer creates a new remote.ByteBuffer using the given netpoll.ZeroCopyWriter. 50 func NewWriterByteBuffer(w netpoll.Writer) remote.ByteBuffer { 51 bytebuf := bytebufPool.Get().(*netpollByteBuffer) 52 bytebuf.writer = w 53 // TODO(wangtieju): fix me when netpoll support netpoll.Writer 54 // and LinkBuffer not support io.Reader, type assertion would fail when w is from NewBuffer 55 if iw, ok := w.(io.Writer); ok { 56 bytebuf.ioWriter = iw 57 } 58 bytebuf.status = remote.BitWritable 59 return bytebuf 60 } 61 62 // NewReaderWriterByteBuffer creates a new remote.ByteBuffer using the given netpoll.ZeroCopyReadWriter. 63 func NewReaderWriterByteBuffer(rw netpoll.ReadWriter) remote.ByteBuffer { 64 bytebuf := bytebufPool.Get().(*netpollByteBuffer) 65 bytebuf.writer = rw 66 bytebuf.reader = rw 67 // TODO(wangtieju): fix me when netpoll support netpoll.ReadWriter 68 // and LinkBuffer not support io.ReadWriter, type assertion would fail when rw is from NewBuffer 69 if irw, ok := rw.(io.ReadWriter); ok { 70 bytebuf.ioReader = irw 71 bytebuf.ioWriter = irw 72 } 73 bytebuf.status = remote.BitWritable | remote.BitReadable 74 return bytebuf 75 } 76 77 func newNetpollByteBuffer() interface{} { 78 return &netpollByteBuffer{} 79 } 80 81 type netpollByteBuffer struct { 82 writer netpoll.Writer 83 reader netpoll.Reader 84 ioReader io.Reader 85 ioWriter io.Writer 86 status int 87 readSize int 88 } 89 90 var _ remote.ByteBuffer = &netpollByteBuffer{} 91 92 // Next reads n bytes sequentially, returns the original address. 93 func (b *netpollByteBuffer) Next(n int) (p []byte, err error) { 94 if b.status&remote.BitReadable == 0 { 95 return nil, errors.New("unreadable buffer, cannot support Next") 96 } 97 if p, err = b.reader.Next(n); err == nil { 98 b.readSize += n 99 } 100 return 101 } 102 103 // Peek returns the next n bytes without advancing the reader. 104 func (b *netpollByteBuffer) Peek(n int) (buf []byte, err error) { 105 if b.status&remote.BitReadable == 0 { 106 return nil, errors.New("unreadable buffer, cannot support Peek") 107 } 108 return b.reader.Peek(n) 109 } 110 111 // Skip is used to skip n bytes, it's much faster than Next. 112 // Skip will not cause release. 113 func (b *netpollByteBuffer) Skip(n int) (err error) { 114 if b.status&remote.BitReadable == 0 { 115 return errors.New("unreadable buffer, cannot support Skip") 116 } 117 return b.reader.Skip(n) 118 } 119 120 // ReadableLen returns the total length of readable buffer. 121 func (b *netpollByteBuffer) ReadableLen() (n int) { 122 if b.status&remote.BitReadable == 0 { 123 return -1 124 } 125 return b.reader.Len() 126 } 127 128 // Read implement io.Reader 129 func (b *netpollByteBuffer) Read(p []byte) (n int, err error) { 130 if b.status&remote.BitReadable == 0 { 131 return -1, errors.New("unreadable buffer, cannot support Read") 132 } 133 if b.ioReader != nil { 134 return b.ioReader.Read(p) 135 } 136 return -1, errors.New("ioReader is nil") 137 } 138 139 // ReadString is a more efficient way to read string than Next. 140 func (b *netpollByteBuffer) ReadString(n int) (s string, err error) { 141 if b.status&remote.BitReadable == 0 { 142 return "", errors.New("unreadable buffer, cannot support ReadString") 143 } 144 if s, err = b.reader.ReadString(n); err == nil { 145 b.readSize += n 146 } 147 return 148 } 149 150 // ReadBinary like ReadString. 151 // Returns a copy of original buffer. 152 func (b *netpollByteBuffer) ReadBinary(n int) (p []byte, err error) { 153 if b.status&remote.BitReadable == 0 { 154 return p, errors.New("unreadable buffer, cannot support ReadBinary") 155 } 156 if p, err = b.reader.ReadBinary(n); err == nil { 157 b.readSize += n 158 } 159 return 160 } 161 162 // Malloc n bytes sequentially in the writer buffer. 163 func (b *netpollByteBuffer) Malloc(n int) (buf []byte, err error) { 164 if b.status&remote.BitWritable == 0 { 165 return nil, errors.New("unwritable buffer, cannot support Malloc") 166 } 167 return b.writer.Malloc(n) 168 } 169 170 // MallocLen returns the total length of the buffer malloced. 171 func (b *netpollByteBuffer) MallocLen() (length int) { 172 if b.status&remote.BitWritable == 0 { 173 return -1 174 } 175 return b.writer.MallocLen() 176 } 177 178 // Write implement io.Writer 179 func (b *netpollByteBuffer) Write(p []byte) (n int, err error) { 180 if b.status&remote.BitWritable == 0 { 181 return -1, errors.New("unwritable buffer, cannot support Write") 182 } 183 if b.ioWriter != nil { 184 return b.ioWriter.Write(p) 185 } 186 return -1, errors.New("ioWriter is nil") 187 } 188 189 // WriteString is a more efficient way to write string, using the unsafe method to convert the string to []byte. 190 func (b *netpollByteBuffer) WriteString(s string) (n int, err error) { 191 if b.status&remote.BitWritable == 0 { 192 return -1, errors.New("unwritable buffer, cannot support WriteString") 193 } 194 return b.writer.WriteString(s) 195 } 196 197 // WriteBinary writes the []byte directly. Callers must guarantee that the []byte doesn't change. 198 func (b *netpollByteBuffer) WriteBinary(p []byte) (n int, err error) { 199 if b.status&remote.BitWritable == 0 { 200 return -1, errors.New("unwritable buffer, cannot support WriteBinary") 201 } 202 return b.writer.WriteBinary(p) 203 } 204 205 // WriteDirect is a way to write []byte without copying, and splits the original buffer. 206 func (b *netpollByteBuffer) WriteDirect(p []byte, remainCap int) error { 207 if b.status&remote.BitWritable == 0 { 208 return errors.New("unwritable buffer, cannot support WriteBinary") 209 } 210 return b.writer.WriteDirect(p, remainCap) 211 } 212 213 // ReadLen returns the size already read. 214 func (b *netpollByteBuffer) ReadLen() (n int) { 215 return b.readSize 216 } 217 218 // Flush writes any malloc data to the underlying io.Writer. 219 // The malloced buffer must be set correctly. 220 func (b *netpollByteBuffer) Flush() (err error) { 221 if b.status&remote.BitWritable == 0 { 222 return errors.New("unwritable buffer, cannot support Flush") 223 } 224 return b.writer.Flush() 225 } 226 227 // NewBuffer returns a new writable remote.ByteBuffer. 228 func (b *netpollByteBuffer) NewBuffer() remote.ByteBuffer { 229 return NewWriterByteBuffer(netpoll.NewLinkBuffer()) 230 } 231 232 // AppendBuffer appends buf to the original buffer. 233 func (b *netpollByteBuffer) AppendBuffer(buf remote.ByteBuffer) (err error) { 234 subBuf := buf.(*netpollByteBuffer) 235 err = b.writer.Append(subBuf.writer) 236 buf.Release(nil) 237 return 238 } 239 240 // Bytes are not supported in netpoll bytebuf. 241 func (b *netpollByteBuffer) Bytes() (buf []byte, err error) { 242 return nil, errors.New("method Bytes() not support in netpoll bytebuf") 243 } 244 245 // Release will free the buffer already read. 246 // After release, buffer read by Next/Skip/Peek is invalid. 247 func (b *netpollByteBuffer) Release(e error) (err error) { 248 if b.reader != nil { 249 // 重复执行Release nil panic 250 err = b.reader.Release() 251 } 252 b.zero() 253 bytebufPool.Put(b) 254 return 255 } 256 257 func (b *netpollByteBuffer) zero() { 258 b.writer = nil 259 b.reader = nil 260 b.ioReader = nil 261 b.ioWriter = nil 262 b.status = 0 263 b.readSize = 0 264 }