github.com/KYVENetwork/cometbft/v38@v38.0.3/libs/flowrate/io.go (about) 1 // 2 // Written by Maxim Khitrov (November 2012) 3 // 4 5 package flowrate 6 7 import ( 8 "errors" 9 "io" 10 ) 11 12 // ErrLimit is returned by the Writer when a non-blocking write is short due to 13 // the transfer rate limit. 14 var ErrLimit = errors.New("flowrate: flow rate limit exceeded") 15 16 // Limiter is implemented by the Reader and Writer to provide a consistent 17 // interface for monitoring and controlling data transfer. 18 type Limiter interface { 19 Done() int64 20 Status() Status 21 SetTransferSize(bytes int64) 22 SetLimit(new int64) (old int64) 23 SetBlocking(new bool) (old bool) 24 } 25 26 // Reader implements io.ReadCloser with a restriction on the rate of data 27 // transfer. 28 type Reader struct { 29 io.Reader // Data source 30 *Monitor // Flow control monitor 31 32 limit int64 // Rate limit in bytes per second (unlimited when <= 0) 33 block bool // What to do when no new bytes can be read due to the limit 34 } 35 36 // NewReader restricts all Read operations on r to limit bytes per second. 37 func NewReader(r io.Reader, limit int64) *Reader { 38 return &Reader{r, New(0, 0), limit, true} 39 } 40 41 // Read reads up to len(p) bytes into p without exceeding the current transfer 42 // rate limit. It returns (0, nil) immediately if r is non-blocking and no new 43 // bytes can be read at this time. 44 func (r *Reader) Read(p []byte) (n int, err error) { 45 p = p[:r.Limit(len(p), r.limit, r.block)] 46 if len(p) > 0 { 47 n, err = r.IO(r.Reader.Read(p)) 48 } 49 return 50 } 51 52 // SetLimit changes the transfer rate limit to new bytes per second and returns 53 // the previous setting. 54 func (r *Reader) SetLimit(new int64) (old int64) { 55 old, r.limit = r.limit, new 56 return 57 } 58 59 // SetBlocking changes the blocking behavior and returns the previous setting. A 60 // Read call on a non-blocking reader returns immediately if no additional bytes 61 // may be read at this time due to the rate limit. 62 func (r *Reader) SetBlocking(new bool) (old bool) { 63 old, r.block = r.block, new 64 return 65 } 66 67 // Close closes the underlying reader if it implements the io.Closer interface. 68 func (r *Reader) Close() error { 69 defer r.Done() 70 if c, ok := r.Reader.(io.Closer); ok { 71 return c.Close() 72 } 73 return nil 74 } 75 76 // Writer implements io.WriteCloser with a restriction on the rate of data 77 // transfer. 78 type Writer struct { 79 io.Writer // Data destination 80 *Monitor // Flow control monitor 81 82 limit int64 // Rate limit in bytes per second (unlimited when <= 0) 83 block bool // What to do when no new bytes can be written due to the limit 84 } 85 86 // NewWriter restricts all Write operations on w to limit bytes per second. The 87 // transfer rate and the default blocking behavior (true) can be changed 88 // directly on the returned *Writer. 89 func NewWriter(w io.Writer, limit int64) *Writer { 90 return &Writer{w, New(0, 0), limit, true} 91 } 92 93 // Write writes len(p) bytes from p to the underlying data stream without 94 // exceeding the current transfer rate limit. It returns (n, ErrLimit) if w is 95 // non-blocking and no additional bytes can be written at this time. 96 func (w *Writer) Write(p []byte) (n int, err error) { 97 var c int 98 for len(p) > 0 && err == nil { 99 s := p[:w.Limit(len(p), w.limit, w.block)] 100 if len(s) > 0 { 101 c, err = w.IO(w.Writer.Write(s)) 102 } else { 103 return n, ErrLimit 104 } 105 p = p[c:] 106 n += c 107 } 108 return 109 } 110 111 // SetLimit changes the transfer rate limit to new bytes per second and returns 112 // the previous setting. 113 func (w *Writer) SetLimit(new int64) (old int64) { 114 old, w.limit = w.limit, new 115 return 116 } 117 118 // SetBlocking changes the blocking behavior and returns the previous setting. A 119 // Write call on a non-blocking writer returns as soon as no additional bytes 120 // may be written at this time due to the rate limit. 121 func (w *Writer) SetBlocking(new bool) (old bool) { 122 old, w.block = w.block, new 123 return 124 } 125 126 // Close closes the underlying writer if it implements the io.Closer interface. 127 func (w *Writer) Close() error { 128 defer w.Done() 129 if c, ok := w.Writer.(io.Closer); ok { 130 return c.Close() 131 } 132 return nil 133 }